From b7acc9ca53d39f64c0624af14dbe5b04fe4bc85e Mon Sep 17 00:00:00 2001 From: teddav Date: Mon, 14 Feb 2022 12:15:24 +0100 Subject: [PATCH] setup repo --- .codecov.yml | 11 + .eslintrc.js | 78 + .github/workflows/ci.yml | 134 + .github/workflows/security.yml | 27 + .gitignore | 55 + .prettierrc | 20 + .solcover.js | 46 + .solhint.json | 15 + .solhintignore | 3 + contracts/external/AccessControl.sol | 233 + .../external/AccessControlUpgradeable.sol | 241 + contracts/external/FullMath.sol | 110 + contracts/external/PoolAddress.sol | 53 + contracts/external/ProxyAdmin.sol | 81 + contracts/external/SmartWalletChecker.sol | 97 + .../external/TransparentUpgradeableProxy.sol | 125 + contracts/genericLender/GenericAave.sol | 452 + contracts/genericLender/GenericCompound.sol | 288 + .../genericLender/GenericCompoundRinkeby.sol | 212 + .../GenericCompoundRinkebyETH.sol | 222 + contracts/genericLender/GenericLenderBase.sol | 107 + contracts/interfaces/IAccessControl.sol | 18 + contracts/interfaces/IAgToken.sol | 27 + contracts/interfaces/IAngleDistributor.sol | 14 + contracts/interfaces/IAngleMiddlemanGauge.sol | 10 + contracts/interfaces/IBondingCurve.sol | 23 + contracts/interfaces/ICollateralSettler.sol | 14 + contracts/interfaces/ICore.sol | 26 + contracts/interfaces/IERC721.sol | 46 + contracts/interfaces/IFeeDistributor.sol | 10 + contracts/interfaces/IFeeManager.sol | 42 + contracts/interfaces/IGaugeController.sol | 14 + contracts/interfaces/IGenericLender.sol | 35 + contracts/interfaces/ILiquidityGauge.sol | 8 + contracts/interfaces/IOracle.sol | 23 + contracts/interfaces/IPerpetualManager.sol | 105 + contracts/interfaces/IPoolManager.sol | 84 + contracts/interfaces/IRewardsDistributor.sol | 52 + contracts/interfaces/ISanToken.sol | 27 + contracts/interfaces/IStableMaster.sol | 168 + contracts/interfaces/IStakingRewards.sol | 27 + contracts/interfaces/IStrategy.sol | 32 + contracts/interfaces/ITimelock.sol | 44 + contracts/interfaces/IWETH.sol | 12 + .../interfaces/external/aave/DataTypes.sol | 44 + contracts/interfaces/external/aave/IAave.sol | 124 + .../interfaces/external/compound/CErc20I.sol | 15 + .../interfaces/external/compound/CEtherI.sol | 13 + .../interfaces/external/compound/CTokenI.sol | 26 + .../external/compound/IComptroller.sol | 16 + .../external/compound/InterestRateModel.sol | 27 + contracts/interfaces/external/curve/Curve.sol | 60 + contracts/interfaces/external/lido/ISteth.sol | 11 + .../external/uniswap/IUniswapRouter.sol | 38 + contracts/interfaces/mock/IERC20MINT.sol | 9 + .../interfaces/mock/IMockUniswapV3Pool.sol | 28 + contracts/mock/MockCurveStETHETH.sol | 48 + contracts/mock/MockStETH.sol | 27 + contracts/mock/MockStrategy.sol | 32 + contracts/mock/MockToken.sol | 51 + contracts/poolManager/PoolManager.sol | 489 + contracts/poolManager/PoolManagerEvents.sol | 47 + contracts/poolManager/PoolManagerInternal.sol | 84 + .../poolManager/PoolManagerStorageV1.sol | 49 + .../poolManager/PoolManagerStorageV2.sol | 15 + .../poolManager/PoolManagerStorageV3.sol | 28 + contracts/stableMaster/StableMaster.sol | 567 + contracts/stableMaster/StableMasterEvents.sol | 64 + contracts/stableMaster/StableMasterFront.sol | 230 + .../stableMaster/StableMasterInternal.sol | 150 + .../stableMaster/StableMasterStorage.sol | 60 + contracts/strategies/BaseStrategy.sol | 447 + contracts/strategies/BaseStrategyEvents.sol | 33 + contracts/strategies/Strategy.sol | 479 + contracts/strategies/StrategyEvents.sol | 22 + contracts/strategies/StrategyStETHAcc.sol | 322 + contracts/utils/FunctionUtils.sol | 97 + contracts/utils/OracleMath.sol | 73 + contracts/utils/PausableMapUpgradeable.sol | 44 + errorMessages.json | 117 + hardhat.config.ts | 170 + package.json | 95 + test/genericLender/GenericAave.test.js | 448 + test/genericLender/GenericCompound.test.js | 323 + test/helpers.js | 501 + test/poolManager/PoolManager.test.js | 510 + test/strategies/Strategy.test.js | 1243 ++ test/strategies/StrategyStETH.test.js | 641 + test/typeScript/helpers.ts | 284 + test/typeScript/testBase.ts | 255 + test/typeScript/testFees.ts | 767 + tsconfig.json | 12 + utils/bignumber.ts | 81 + utils/network.ts | 44 + utils/uniswap.ts | 159 + yarn.lock | 13034 ++++++++++++++++ 96 files changed, 26024 insertions(+) create mode 100644 .codecov.yml create mode 100644 .eslintrc.js create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/security.yml create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 .solcover.js create mode 100644 .solhint.json create mode 100644 .solhintignore create mode 100644 contracts/external/AccessControl.sol create mode 100644 contracts/external/AccessControlUpgradeable.sol create mode 100644 contracts/external/FullMath.sol create mode 100644 contracts/external/PoolAddress.sol create mode 100644 contracts/external/ProxyAdmin.sol create mode 100644 contracts/external/SmartWalletChecker.sol create mode 100644 contracts/external/TransparentUpgradeableProxy.sol create mode 100644 contracts/genericLender/GenericAave.sol create mode 100644 contracts/genericLender/GenericCompound.sol create mode 100644 contracts/genericLender/GenericCompoundRinkeby.sol create mode 100644 contracts/genericLender/GenericCompoundRinkebyETH.sol create mode 100644 contracts/genericLender/GenericLenderBase.sol create mode 100644 contracts/interfaces/IAccessControl.sol create mode 100644 contracts/interfaces/IAgToken.sol create mode 100644 contracts/interfaces/IAngleDistributor.sol create mode 100644 contracts/interfaces/IAngleMiddlemanGauge.sol create mode 100644 contracts/interfaces/IBondingCurve.sol create mode 100644 contracts/interfaces/ICollateralSettler.sol create mode 100644 contracts/interfaces/ICore.sol create mode 100644 contracts/interfaces/IERC721.sol create mode 100644 contracts/interfaces/IFeeDistributor.sol create mode 100644 contracts/interfaces/IFeeManager.sol create mode 100644 contracts/interfaces/IGaugeController.sol create mode 100644 contracts/interfaces/IGenericLender.sol create mode 100644 contracts/interfaces/ILiquidityGauge.sol create mode 100644 contracts/interfaces/IOracle.sol create mode 100644 contracts/interfaces/IPerpetualManager.sol create mode 100644 contracts/interfaces/IPoolManager.sol create mode 100644 contracts/interfaces/IRewardsDistributor.sol create mode 100644 contracts/interfaces/ISanToken.sol create mode 100644 contracts/interfaces/IStableMaster.sol create mode 100644 contracts/interfaces/IStakingRewards.sol create mode 100644 contracts/interfaces/IStrategy.sol create mode 100644 contracts/interfaces/ITimelock.sol create mode 100644 contracts/interfaces/IWETH.sol create mode 100644 contracts/interfaces/external/aave/DataTypes.sol create mode 100644 contracts/interfaces/external/aave/IAave.sol create mode 100755 contracts/interfaces/external/compound/CErc20I.sol create mode 100644 contracts/interfaces/external/compound/CEtherI.sol create mode 100644 contracts/interfaces/external/compound/CTokenI.sol create mode 100644 contracts/interfaces/external/compound/IComptroller.sol create mode 100755 contracts/interfaces/external/compound/InterestRateModel.sol create mode 100644 contracts/interfaces/external/curve/Curve.sol create mode 100644 contracts/interfaces/external/lido/ISteth.sol create mode 100644 contracts/interfaces/external/uniswap/IUniswapRouter.sol create mode 100644 contracts/interfaces/mock/IERC20MINT.sol create mode 100644 contracts/interfaces/mock/IMockUniswapV3Pool.sol create mode 100644 contracts/mock/MockCurveStETHETH.sol create mode 100644 contracts/mock/MockStETH.sol create mode 100644 contracts/mock/MockStrategy.sol create mode 100644 contracts/mock/MockToken.sol create mode 100644 contracts/poolManager/PoolManager.sol create mode 100644 contracts/poolManager/PoolManagerEvents.sol create mode 100644 contracts/poolManager/PoolManagerInternal.sol create mode 100644 contracts/poolManager/PoolManagerStorageV1.sol create mode 100644 contracts/poolManager/PoolManagerStorageV2.sol create mode 100644 contracts/poolManager/PoolManagerStorageV3.sol create mode 100644 contracts/stableMaster/StableMaster.sol create mode 100644 contracts/stableMaster/StableMasterEvents.sol create mode 100644 contracts/stableMaster/StableMasterFront.sol create mode 100644 contracts/stableMaster/StableMasterInternal.sol create mode 100644 contracts/stableMaster/StableMasterStorage.sol create mode 100644 contracts/strategies/BaseStrategy.sol create mode 100644 contracts/strategies/BaseStrategyEvents.sol create mode 100644 contracts/strategies/Strategy.sol create mode 100644 contracts/strategies/StrategyEvents.sol create mode 100644 contracts/strategies/StrategyStETHAcc.sol create mode 100644 contracts/utils/FunctionUtils.sol create mode 100644 contracts/utils/OracleMath.sol create mode 100644 contracts/utils/PausableMapUpgradeable.sol create mode 100644 errorMessages.json create mode 100644 hardhat.config.ts create mode 100644 package.json create mode 100644 test/genericLender/GenericAave.test.js create mode 100644 test/genericLender/GenericCompound.test.js create mode 100644 test/helpers.js create mode 100644 test/poolManager/PoolManager.test.js create mode 100644 test/strategies/Strategy.test.js create mode 100644 test/strategies/StrategyStETH.test.js create mode 100644 test/typeScript/helpers.ts create mode 100644 test/typeScript/testBase.ts create mode 100644 test/typeScript/testFees.ts create mode 100644 tsconfig.json create mode 100644 utils/bignumber.ts create mode 100644 utils/network.ts create mode 100644 utils/uniswap.ts create mode 100644 yarn.lock diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..8de72d0 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,11 @@ +comment: off +github_checks: + annotations: false +coverage: + status: + patch: + default: + target: 97% + project: + default: + threshold: 1% diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..113ed68 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,78 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'standard', + 'plugin:promise/recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['mocha-no-only', 'promise', 'prettier', '@typescript-eslint'], + env: { + browser: true, + node: true, + mocha: true, + jest: true, + }, + globals: { + artifacts: false, + contract: false, + assert: false, + web3: false, + usePlugin: false, + extendEnvironment: false, + }, + rules: { + // Strict mode + strict: ['error', 'global'], + 'prettier/prettier': 'error', + // Code style + 'array-bracket-spacing': ['off'], + camelcase: ['error', { properties: 'always', ignoreImports: true }], + 'comma-dangle': ['error', 'always-multiline'], + 'comma-spacing': ['error', { before: false, after: true }], + 'dot-notation': ['error', { allowKeywords: true, allowPattern: '' }], + 'eol-last': ['error', 'always'], + eqeqeq: ['error', 'smart'], + 'generator-star-spacing': ['error', 'before'], + 'linebreak-style': ['error', 'unix'], + 'max-len': ['error', 150, 2, { ignoreComments: true }], + 'no-debugger': 'off', + 'no-dupe-args': 'error', + 'no-dupe-keys': 'error', + 'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'], + 'no-redeclare': ['error', { builtinGlobals: true }], + 'no-trailing-spaces': ['error', { skipBlankLines: false }], + 'no-undef': 'error', + 'no-use-before-define': 'off', + 'no-var': 'error', + 'object-curly-spacing': ['error', 'always'], + 'prefer-const': 'error', + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'space-before-function-paren': 0, + '@typescript-eslint/no-non-null-assertion': 0, + + 'mocha-no-only/mocha-no-only': ['error'], + + 'promise/always-return': 'off', + 'promise/avoid-new': 'off', + }, + overrides: [ + { + files: ['*.js'], + rules: { + '@typescript-eslint/no-var-requires': [0], + }, + }, + { + files: ['./test/**/*'], + rules: { + camelcase: [0], + }, + }, + ], + parserOptions: { + ecmaVersion: 2018, + }, +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ca496e7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,134 @@ +name: CI + +on: + push: + branches: + - main + workflow_dispatch: + inputs: + workflow_to_run: + type: choice + description: Which workflow to run? + required: true + options: + - all + - all_brownie + - brownie-curve + - brownie-protocol + - unit_tests + +defaults: + run: + shell: bash + +jobs: + run-linters: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - uses: actions/cache@v2 + with: + path: node_modules + key: yarn-${{ hashFiles('yarn.lock') }} + restore-keys: yarn- + - name: Install dependencies + run: | + npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN + yarn install --frozen-lockfile + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Run solhint + run: yarn lint:sol + - name: Run eslint + run: yarn lint:js:fix + - name: Discord notification + if: failure() + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + with: + args: '⛔️ Error in project {{EVENT_PAYLOAD.repository.full_name}}. See here: https://github.com/AngleProtocol/angle-solidity/actions' + + unit-tests: + if: ${{ github.ref == 'refs/heads/main' || github.event.inputs.workflow_to_run == 'all' || github.event.inputs.workflow_to_run == 'unit_tests' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - uses: actions/cache@v2 + with: + path: node_modules + key: yarn-${{ hashFiles('yarn.lock') }} + restore-keys: yarn- + - name: Install dependencies + run: | + npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN + yarn install --frozen-lockfile + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + # This is required separately from yarn test because it generates the typechain definitions + - name: Compile + run: yarn compile + - name: Run unit tests + run: yarn test + env: + ENABLE_GAS_REPORT: true + CI: true + - name: Print gas report + run: cat gas-report.txt + - name: Discord notification + if: failure() + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + with: + args: '⛔️ Error in project {{EVENT_PAYLOAD.repository.full_name}}. See here: https://github.com/AngleProtocol/angle-solidity/actions' + + brownie-tests-curve: + if: ${{ github.ref == 'refs/heads/main' || github.event.inputs.workflow_to_run == 'all' || github.event.inputs.workflow_to_run == 'all_brownie' || github.event.inputs.workflow_to_run == 'brownie-curve' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - uses: actions/setup-python@v2 + with: + python-version: '3.8' # Version range or exact version of a Python version to use, using SemVer's version range syntax + - run: npm install -g ganache-cli + - run: pip install -r requirements.txt + - run: brownie test testBrownie/CurveSystem + - name: Discord notification + if: failure() + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + with: + args: '⛔️ Error in project {{EVENT_PAYLOAD.repository.full_name}}. See here: https://github.com/AngleProtocol/angle-solidity/actions' + brownie-tests-protocol: + if: ${{ github.ref == 'refs/heads/main' || github.event.inputs.workflow_to_run == 'all' || github.event.inputs.workflow_to_run == 'all_brownie' || github.event.inputs.workflow_to_run == 'brownie-protocol' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - uses: actions/setup-python@v2 + with: + python-version: '3.8' # Version range or exact version of a Python version to use, using SemVer's version range syntax + - run: npm install -g ganache-cli + - run: pip install -r requirements.txt + - run: brownie test testBrownie/ProtocolTests + - name: Discord notification + if: failure() + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + with: + args: '⛔️ Error in project {{EVENT_PAYLOAD.repository.full_name}}. See here: https://github.com/AngleProtocol/angle-solidity/actions' diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..425b21c --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,27 @@ +name: Security analysis + +on: [workflow_dispatch] + +defaults: + run: + shell: bash + +jobs: + slither: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' + - uses: actions/setup-python@v2 + with: + python-version: '3.x' + - run: pip3 install slither-analyzer + - run: | + npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN + yarn install + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - run: slither . + # slither . --filter-paths contracts/mock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d9f83e --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +## Defaults +__pycache__ +.idea +.DS_Store +.deps +.vscode +.docs +.env +node_modules +tenderly.yaml +settings.json +.mocharc.json +venv + +# Build output +cache +build +export +**/artifacts +.openzeppelin +docgen/docs +docgen/SUMMARY.md +solidity-flattenedContracts +./crytic-export +typechain + + +# Test output +coverage +coverage.json + +# Running output +gas-report.txt +gasReporterOutput.json +addresses.json +blockchain_db +ganache* +yarn-error.log + +# deployments +deployments/* +!deployments/kovan +!deployments/rinkeby +!deployments/mainnet +!deployments/polygon + +# bin +bin + +# temporary delete +test/perpetualManager/perpetualManagerChangeBase.test.js +typechain/cacheIndex.ts + +# used for storing temporary vyper artifacts +vyper_temp_dir diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2ecfc04 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,20 @@ +{ + "arrowParens": "avoid", + "jsxSingleQuote": true, + "singleQuote": true, + "printWidth": 120, + "semi": true, + "trailingComma": "all", + "useTabs": false, + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 120, + "singleQuote": false, + "bracketSpacing": true, + "explicitTypes": "always" + } + } + ] +} diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 0000000..fe43167 --- /dev/null +++ b/.solcover.js @@ -0,0 +1,46 @@ +module.exports = { + norpc: true, + testCommand: 'yarn test', + compileCommand: 'yarn compile:hardhat', + skipFiles: [ + 'mock', + 'external', + 'interfaces', + 'sigp', + 'bondingCurve/BondingCurveEvents.sol', + 'collateralSettler/CollateralSettlerVeANGLEEvents.sol', + 'dao/Governor.sol', + 'dao/GovernorStorage.sol', + 'dao/GovernorEvents.sol', + 'dao/TimelockEvents.sol', + 'dao/Temporary.sol', + 'poolManager/PoolManagerEvents.sol', + 'poolManager/PoolManagerStorageV1.sol', + 'poolManager/PoolManagerStorageV2.sol', + 'poolManager/PoolManagerStorageV3.sol', + 'feeManager/FeeManagerEvents.sol', + 'feeManager/FeeManagerStorage.sol', + 'oracle/OracleChainlinkMulti.sol', + 'stableMaster/StableMasterEvents.sol', + 'stableMaster/StableMasterStorage.sol', + 'staking/RewardsDistributorEvents.sol', + 'staking/StakingRewardsEvents.sol', + 'staking/StrategyWETH.sol', + 'strategies/BaseStrategyEvents.sol', + 'utils/OracleMath.sol', + 'utils/PoolAddress.sol', + 'perpetualManager/PerpetualManagerEvents.sol', + 'perpetualManager/PerpetualManagerStorage.sol', + 'genericLender/GenericDyDx.sol', + 'genericLender/GenericCompoundRinkeby.sol', + 'genericLender/GenericCompoundRinkebyETH.sol', + 'webscrap', + ], + providerOptions: { + default_balance_ether: '10000000000000000000000000', + }, + mocha: { + fgrep: '[skip-on-coverage]', + invert: true, + }, +}; diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 0000000..88814e5 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,15 @@ +{ + "extends": "solhint:recommended", + "plugins": ["prettier"], + "rules": { + "prettier/prettier": "warning", + "ordering": "off", + "mark-callable-contracts": "off", + "no-empty-blocks": "off", + "not-rely-on-time": "off", + "compiler-version": "off", + "private-vars-leading-underscore": "error", + "reason-string": "off", + "func-visibility": ["error", { "ignoreConstructors": true }] + } +} diff --git a/.solhintignore b/.solhintignore new file mode 100644 index 0000000..c10b8c8 --- /dev/null +++ b/.solhintignore @@ -0,0 +1,3 @@ +mock/ +external/ +contracts/dao/Temporary.sol diff --git a/contracts/external/AccessControl.sol b/contracts/external/AccessControl.sol new file mode 100644 index 0000000..bfa8c2a --- /dev/null +++ b/contracts/external/AccessControl.sol @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +import "../interfaces/IAccessControl.sol"; + +/** + * @dev This contract is fully forked from OpenZeppelin `AccessControl`. + * The only difference is the removal of the ERC165 implementation as it's not + * needed in Angle. + * + * Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +abstract contract AccessControl is Context, IAccessControl { + struct RoleData { + mapping(address => bool) members; + bytes32 adminRole; + } + + mapping(bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with a standardized message including the required role. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ + * + * _Available since v4.1._ + */ + modifier onlyRole(bytes32 role) { + _checkRole(role, _msgSender()); + _; + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view override returns (bool) { + return _roles[role].members[account]; + } + + /** + * @dev Revert with a standard message if `account` is missing `role`. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ + */ + function _checkRole(bytes32 role, address account) internal view { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(uint160(account), 20), + " is missing role ", + Strings.toHexString(uint256(role), 32) + ) + ) + ); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view override returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) external override { + require(account == _msgSender(), "71"); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + */ + function _setupRole(bytes32 role, address account) internal { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal { + emit RoleAdminChanged(role, getRoleAdmin(role), adminRole); + _roles[role].adminRole = adminRole; + } + + function _grantRole(bytes32 role, address account) internal { + if (!hasRole(role, account)) { + _roles[role].members[account] = true; + emit RoleGranted(role, account, _msgSender()); + } + } + + function _revokeRole(bytes32 role, address account) internal { + if (hasRole(role, account)) { + _roles[role].members[account] = false; + emit RoleRevoked(role, account, _msgSender()); + } + } +} diff --git a/contracts/external/AccessControlUpgradeable.sol b/contracts/external/AccessControlUpgradeable.sol new file mode 100644 index 0000000..e2ac108 --- /dev/null +++ b/contracts/external/AccessControlUpgradeable.sol @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "../interfaces/IAccessControl.sol"; + +/** + * @dev This contract is fully forked from OpenZeppelin `AccessControlUpgradeable`. + * The only difference is the removal of the ERC165 implementation as it's not + * needed in Angle. + * + * Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +abstract contract AccessControlUpgradeable is Initializable, IAccessControl { + function __AccessControl_init() internal initializer { + __AccessControl_init_unchained(); + } + + function __AccessControl_init_unchained() internal initializer {} + + struct RoleData { + mapping(address => bool) members; + bytes32 adminRole; + } + + mapping(bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with a standardized message including the required role. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ + * + * _Available since v4.1._ + */ + modifier onlyRole(bytes32 role) { + _checkRole(role, msg.sender); + _; + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view override returns (bool) { + return _roles[role].members[account]; + } + + /** + * @dev Revert with a standard message if `account` is missing `role`. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ + */ + function _checkRole(bytes32 role, address account) internal view { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + StringsUpgradeable.toHexString(uint160(account), 20), + " is missing role ", + StringsUpgradeable.toHexString(uint256(role), 32) + ) + ) + ); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view override returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) external override { + require(account == msg.sender, "71"); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + */ + function _setupRole(bytes32 role, address account) internal { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal { + emit RoleAdminChanged(role, getRoleAdmin(role), adminRole); + _roles[role].adminRole = adminRole; + } + + function _grantRole(bytes32 role, address account) internal { + if (!hasRole(role, account)) { + _roles[role].members[account] = true; + emit RoleGranted(role, account, msg.sender); + } + } + + function _revokeRole(bytes32 role, address account) internal { + if (hasRole(role, account)) { + _roles[role].members[account] = false; + emit RoleRevoked(role, account, msg.sender); + } + } + + uint256[49] private __gap; +} diff --git a/contracts/external/FullMath.sol b/contracts/external/FullMath.sol new file mode 100644 index 0000000..47cd14a --- /dev/null +++ b/contracts/external/FullMath.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.4.0; + +/// @title Contains 512-bit math functions +/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision +/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits +/// @dev This contract was forked from Uniswap V3's contract `FullMath.sol` available here +/// https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/FullMath.sol +abstract contract FullMath { + /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 + /// @param a The multiplicand + /// @param b The multiplier + /// @param denominator The divisor + /// @return result The 256-bit result + /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv + function _mulDiv( + uint256 a, + uint256 b, + uint256 denominator + ) internal pure returns (uint256 result) { + // 512-bit multiply [prod1 prod0] = a * b + // Compute the product mod 2**256 and mod 2**256 - 1 + // then use the Chinese Remainder Theorem to reconstruct + // the 512 bit result. The result is stored in two 256 + // variables such that product = prod1 * 2**256 + prod0 + uint256 prod0; // Least significant 256 bits of the product + uint256 prod1; // Most significant 256 bits of the product + assembly { + let mm := mulmod(a, b, not(0)) + prod0 := mul(a, b) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + // Handle non-overflow cases, 256 by 256 division + if (prod1 == 0) { + require(denominator > 0); + assembly { + result := div(prod0, denominator) + } + return result; + } + + // Make sure the result is less than 2**256. + // Also prevents denominator == 0 + require(denominator > prod1); + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [prod1 prod0] + // Compute remainder using mulmod + uint256 remainder; + assembly { + remainder := mulmod(a, b, denominator) + } + // Subtract 256 bit number from 512 bit number + assembly { + prod1 := sub(prod1, gt(remainder, prod0)) + prod0 := sub(prod0, remainder) + } + + // Factor powers of two out of denominator + // Compute largest power of two divisor of denominator. + // Always >= 1. + uint256 twos = denominator & (~denominator + 1); + // Divide denominator by power of two + assembly { + denominator := div(denominator, twos) + } + + // Divide [prod1 prod0] by the factors of two + assembly { + prod0 := div(prod0, twos) + } + // Shift in bits from prod1 into prod0. For this we need + // to flip `twos` such that it is 2**256 / twos. + // If twos is zero, then it becomes one + assembly { + twos := add(div(sub(0, twos), twos), 1) + } + prod0 |= prod1 * twos; + + // Invert denominator mod 2**256 + // Now that denominator is an odd number, it has an inverse + // modulo 2**256 such that denominator * inv = 1 mod 2**256. + // Compute the inverse by starting with a seed that is correct + // correct for four bits. That is, denominator * inv = 1 mod 2**4 + uint256 inv = (3 * denominator) ^ 2; + // Now use Newton-Raphson iteration to improve the precision. + // Thanks to Hensel's lifting lemma, this also works in modular + // arithmetic, doubling the correct bits in each step. + inv *= 2 - denominator * inv; // inverse mod 2**8 + inv *= 2 - denominator * inv; // inverse mod 2**16 + inv *= 2 - denominator * inv; // inverse mod 2**32 + inv *= 2 - denominator * inv; // inverse mod 2**64 + inv *= 2 - denominator * inv; // inverse mod 2**128 + inv *= 2 - denominator * inv; // inverse mod 2**256 + + // Because the division is now exact we can divide by multiplying + // with the modular inverse of denominator. This will give us the + // correct result modulo 2**256. Since the precoditions guarantee + // that the outcome is less than 2**256, this is the final result. + // We don't need to compute the high bits of the result and prod1 + // is no longer required. + result = prod0 * inv; + return result; + } +} diff --git a/contracts/external/PoolAddress.sol b/contracts/external/PoolAddress.sol new file mode 100644 index 0000000..871a668 --- /dev/null +++ b/contracts/external/PoolAddress.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title PoolAddress +/// @author Forked from UniswapV3's contract `PoolAddress` +/// @notice Provides functions for deriving a pool address from the factory, tokens, and the fee +contract PoolAddress { + bytes32 internal constant _POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; + + /// @notice The identifying key of the pool + struct PoolKey { + address token0; + address token1; + uint24 fee; + } + + /// @notice Returns PoolKey: the ordered tokens with the matched fee levels + /// @param tokenA The first token of a pool, unsorted + /// @param tokenB The second token of a pool, unsorted + /// @param fee The fee level of the pool + /// @return Poolkey The pool details with ordered token0 and token1 assignments + function getPoolKey( + address tokenA, + address tokenB, + uint24 fee + ) external pure returns (PoolKey memory) { + if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); + return PoolKey({ token0: tokenA, token1: tokenB, fee: fee }); + } + + /// @notice Deterministically computes the pool address given the factory and PoolKey + /// @param factory The Uniswap V3 factory contract address + /// @param key The PoolKey + /// @return pool The contract address of the V3 pool + function computeAddress(address factory, PoolKey memory key) external pure returns (address pool) { + require(key.token0 < key.token1); + pool = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256(abi.encode(key.token0, key.token1, key.fee)), + _POOL_INIT_CODE_HASH + ) + ) + ) + ) + ); + } +} diff --git a/contracts/external/ProxyAdmin.sol b/contracts/external/ProxyAdmin.sol new file mode 100644 index 0000000..cfaed41 --- /dev/null +++ b/contracts/external/ProxyAdmin.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./TransparentUpgradeableProxy.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an + * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. + * This contract was fully forked from OpenZeppelin `ProxyAdmin` + */ +contract ProxyAdmin is Ownable { + /** + * @dev Returns the current implementation of `proxy`. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) { + // We need to manually run the static call since the getter cannot be flagged as view + // bytes4(keccak256("implementation()")) == 0x5c60da1b + (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); + require(success); + return abi.decode(returndata, (address)); + } + + /** + * @dev Returns the current admin of `proxy`. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) { + // We need to manually run the static call since the getter cannot be flagged as view + // bytes4(keccak256("admin()")) == 0xf851a440 + (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); + require(success); + return abi.decode(returndata, (address)); + } + + /** + * @dev Changes the admin of `proxy` to `newAdmin`. + * + * Requirements: + * + * - This contract must be the current admin of `proxy`. + */ + function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { + proxy.changeAdmin(newAdmin); + } + + /** + * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { + proxy.upgradeTo(implementation); + } + + /** + * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See + * {TransparentUpgradeableProxy-upgradeToAndCall}. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function upgradeAndCall( + TransparentUpgradeableProxy proxy, + address implementation, + bytes memory data + ) public payable virtual onlyOwner { + proxy.upgradeToAndCall{ value: msg.value }(implementation, data); + } +} diff --git a/contracts/external/SmartWalletChecker.sol b/contracts/external/SmartWalletChecker.sol new file mode 100644 index 0000000..addc40a --- /dev/null +++ b/contracts/external/SmartWalletChecker.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.7; + +/// @notice Interface of the `SmartWalletChecker` contracts of the protocol +interface SmartWalletChecker { + function check(address) external view returns (bool); +} + +/// @title SmartWalletWhitelist +/// @author Curve Finance and adapted by Angle Core Team (https://etherscan.io/address/0xca719728ef172d0961768581fdf35cb116e0b7a4#code) +/// @notice Provides functions to check whether a wallet has been verified or not to own veANGLE +contract SmartWalletWhitelist { + /// @notice Mapping between addresses and whether they are whitelisted or not + mapping(address => bool) public wallets; + /// @notice Admin address of the contract + address public admin; + /// @notice Future admin address of the contract + //solhint-disable-next-line + address public future_admin; + /// @notice Contract which works as this contract and that can whitelist addresses + address public checker; + /// @notice Future address to become checker + //solhint-disable-next-line + address public future_checker; + + event ApproveWallet(address indexed _wallet); + event RevokeWallet(address indexed _wallet); + + /// @notice Constructor of the contract + /// @param _admin Admin address of the contract + constructor(address _admin) { + require(_admin != address(0), "0"); + admin = _admin; + } + + /// @notice Commits to change the admin + /// @param _admin New admin of the contract + function commitAdmin(address _admin) external { + require(msg.sender == admin, "!admin"); + future_admin = _admin; + } + + /// @notice Changes the admin to the admin that has been committed + function applyAdmin() external { + require(msg.sender == admin, "!admin"); + require(future_admin != address(0), "admin not set"); + admin = future_admin; + } + + /// @notice Commits to change the checker address + /// @param _checker New checker address + /// @dev This address can be the zero address in which case there will be no checker + function commitSetChecker(address _checker) external { + require(msg.sender == admin, "!admin"); + future_checker = _checker; + } + + /// @notice Applies the checker previously committed + function applySetChecker() external { + require(msg.sender == admin, "!admin"); + checker = future_checker; + } + + /// @notice Approves a wallet + /// @param _wallet Wallet to approve + function approveWallet(address _wallet) public { + require(msg.sender == admin, "!admin"); + wallets[_wallet] = true; + + emit ApproveWallet(_wallet); + } + + /// @notice Revokes a wallet + /// @param _wallet Wallet to revoke + function revokeWallet(address _wallet) external { + require(msg.sender == admin, "!admin"); + wallets[_wallet] = false; + + emit RevokeWallet(_wallet); + } + + /// @notice Checks whether a wallet is whitelisted + /// @param _wallet Wallet address to check + /// @dev This function can also rely on another SmartWalletChecker (a `checker` to see whether the wallet is whitelisted or not) + function check(address _wallet) external view returns (bool) { + bool _check = wallets[_wallet]; + if (_check) { + return _check; + } else { + if (checker != address(0)) { + return SmartWalletChecker(checker).check(_wallet); + } + } + return false; + } +} diff --git a/contracts/external/TransparentUpgradeableProxy.sol b/contracts/external/TransparentUpgradeableProxy.sol new file mode 100644 index 0000000..2bb6caa --- /dev/null +++ b/contracts/external/TransparentUpgradeableProxy.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +/** + * @dev This contract implements a proxy that is upgradeable by an admin. It is fully forked from OpenZeppelin + * `TransparentUpgradeableProxy` + * + * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector + * clashing], which can potentially be used in an attack, this contract uses the + * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two + * things that go hand in hand: + * + * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if + * that call matches one of the admin functions exposed by the proxy itself. + * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the + * implementation. If the admin tries to call a function on the implementation it will fail with an error that says + * "admin cannot fallback to proxy target". + * + * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing + * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due + * to sudden errors when trying to call a function from the proxy implementation. + * + * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, + * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. + */ +contract TransparentUpgradeableProxy is ERC1967Proxy { + /** + * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and + * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. + */ + constructor( + address _logic, + address admin_, + bytes memory _data + ) payable ERC1967Proxy(_logic, _data) { + assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); + _changeAdmin(admin_); + } + + /** + * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. + */ + modifier ifAdmin() { + if (msg.sender == _getAdmin()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev Returns the current admin. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` + */ + function admin() external ifAdmin returns (address admin_) { + admin_ = _getAdmin(); + } + + /** + * @dev Returns the current implementation. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` + */ + function implementation() external ifAdmin returns (address implementation_) { + implementation_ = _implementation(); + } + + /** + * @dev Changes the admin of the proxy. + * + * Emits an {AdminChanged} event. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. + */ + function changeAdmin(address newAdmin) external virtual ifAdmin { + _changeAdmin(newAdmin); + } + + /** + * @dev Upgrade the implementation of the proxy. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. + */ + function upgradeTo(address newImplementation) external ifAdmin { + _upgradeToAndCall(newImplementation, bytes(""), false); + } + + /** + * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified + * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the + * proxied contract. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. + */ + function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { + _upgradeToAndCall(newImplementation, data, true); + } + + /** + * @dev Returns the current admin. + */ + function _admin() internal view virtual returns (address) { + return _getAdmin(); + } + + /** + * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. + */ + function _beforeFallback() internal virtual override { + require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); + super._beforeFallback(); + } +} diff --git a/contracts/genericLender/GenericAave.sol b/contracts/genericLender/GenericAave.sol new file mode 100644 index 0000000..501473f --- /dev/null +++ b/contracts/genericLender/GenericAave.sol @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../interfaces/external/uniswap/IUniswapRouter.sol"; +import "../interfaces/external/aave/IAave.sol"; + +import "./GenericLenderBase.sol"; + +struct AaveReferences { + IAToken aToken; + IProtocolDataProvider protocolDataProvider; + IStakedAave stkAave; + address aave; +} + +/// @title GenericAave +/// @author Forked from https://github.com/Grandthrax/yearnV2-generic-lender-strat/blob/master/contracts/GenericLender/GenericAave.sol +/// @notice A contract to lend any ERC20 to Aave +/// @dev This contract is already in production, see at 0x71bE8726C96873F04d2690AA05b2ACcA7C7104d0 or there: https://etherscan.io/address/0xb164c0f42d9C6DBf976b60962fFe790A35e42b13#code +contract GenericAave is GenericLenderBase { + using SafeERC20 for IERC20; + using Address for address; + + event PathUpdated(bytes _path); + event IncentivisedUpdated(bool _isIncentivised); + event CustomReferralUpdated(uint16 customReferral); + + uint256 internal constant _SECONDS_IN_YEAR = 365 days; + uint16 internal constant _DEFAULT_REFERRAL = 179; // jmonteer's referral code + + // ==================== References to contracts ============================= + address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + + IAToken public immutable aToken; + IProtocolDataProvider public immutable protocolDataProvider; + IStakedAave public immutable stkAave; + address public immutable aave; + IUniswapV3Router public immutable uniswapV3Router; + // Used to get the `want` price of the AAVE token + IUniswapV2Router public immutable uniswapV2Router; + + // ==================== Parameters ============================= + + bytes public path; + bool public isIncentivised; + uint16 internal _customReferral; + + // ============================= Constructor ============================= + + /// @param _path Bytes to encode the swap from aave to want + constructor( + address _strategy, + string memory name, + IUniswapV3Router _uniswapV3Router, + IUniswapV2Router _uniswapV2Router, + AaveReferences memory aaveReferences, + bool _isIncentivised, + bytes memory _path, + address[] memory governorList, + address guardian + ) GenericLenderBase(_strategy, name, governorList, guardian) { + // This transaction is going to revert if `_strategy`, `aave`, `protocolDataProvider` or `aToken` + // are equal to the zero address + require( + address(_uniswapV2Router) != address(0) && + address(_uniswapV3Router) != address(0) && + address(aaveReferences.stkAave) != address(0), + "0" + ); + require( + !_isIncentivised || address(aaveReferences.aToken.getIncentivesController()) != address(0), + "aToken does not have incentives controller set up" + ); + uniswapV3Router = _uniswapV3Router; + uniswapV2Router = _uniswapV2Router; + aToken = aaveReferences.aToken; + protocolDataProvider = aaveReferences.protocolDataProvider; + stkAave = aaveReferences.stkAave; + aave = aaveReferences.aave; + isIncentivised = _isIncentivised; + path = _path; + ILendingPool lendingPool = ILendingPool( + aaveReferences.protocolDataProvider.ADDRESSES_PROVIDER().getLendingPool() + ); + // We cannot store a `lendingPool` variable here otherwise we would get a stack too deep problem + require( + lendingPool.getReserveData(address(want)).aTokenAddress == address(aaveReferences.aToken), + "wrong aToken" + ); + IERC20(address(want)).safeApprove(address(lendingPool), type(uint256).max); + // Approving the Uniswap router for the transactions + IERC20(aaveReferences.aave).safeApprove(address(_uniswapV3Router), type(uint256).max); + } + + // ============================= External Functions ============================= + + /// @notice Deposits the current balance to the lending platform + function deposit() external override onlyRole(STRATEGY_ROLE) { + uint256 balance = want.balanceOf(address(this)); + _deposit(balance); + } + + /// @notice Withdraws a given amount from lender + /// @param amount Amount to withdraw + /// @return Amount actually withdrawn + function withdraw(uint256 amount) external override onlyRole(STRATEGY_ROLE) returns (uint256) { + return _withdraw(amount); + } + + /// @notice Withdraws as much as possible in case of emergency and sends it to the `PoolManager` + /// @param amount Amount to withdraw + /// @dev Does not check if any error occurs or if the amount withdrawn is correct + function emergencyWithdraw(uint256 amount) external override onlyRole(GUARDIAN_ROLE) { + _lendingPool().withdraw(address(want), amount, address(this)); + + want.safeTransfer(address(poolManager), want.balanceOf(address(this))); + } + + /// @notice Withdraws as much as possible + function withdrawAll() external override onlyRole(STRATEGY_ROLE) returns (bool) { + uint256 invested = _nav(); + uint256 returned = _withdraw(invested); + return returned >= invested; + } + + function startCooldown() external onlyRole(GUARDIAN_ROLE) { + // for emergency cases + IStakedAave(stkAave).cooldown(); // it will revert if balance of stkAave == 0 + } + + /// @notice Trigger to claim rewards once every 10 days + /// Only callable if the token is incentivised by Aave Governance (_checkCooldown returns true) + /// @dev Only for incentivised aTokens + function harvest() external { + require(_checkCooldown(), "conditions are not met"); + // redeem AAVE from stkAave + uint256 stkAaveBalance = IERC20(address(stkAave)).balanceOf(address(this)); + if (stkAaveBalance > 0) { + stkAave.redeem(address(this), stkAaveBalance); + } + + // sell AAVE for want + uint256 aaveBalance = IERC20(aave).balanceOf(address(this)); + _sellAAVEForWant(aaveBalance); + + // deposit want in lending protocol + uint256 balance = want.balanceOf(address(this)); + if (balance > 0) { + _deposit(balance); + } + + // claim rewards + address[] memory assets = new address[](1); + assets[0] = address(aToken); + uint256 pendingRewards = _incentivesController().getRewardsBalance(assets, address(this)); + if (pendingRewards > 0) { + _incentivesController().claimRewards(assets, pendingRewards, address(this)); + } + + // request start of cooldown period + if (IERC20(address(stkAave)).balanceOf(address(this)) > 0) { + stkAave.cooldown(); + } + } + + // ============================= External View Functions ============================= + + /// @notice Returns the current total of assets managed + function nav() external view override returns (uint256) { + return _nav(); + } + + /// @notice Returns the current balance of aTokens + function underlyingBalanceStored() public view returns (uint256 balance) { + balance = aToken.balanceOf(address(this)); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate + function apr() external view override returns (uint256) { + return _apr(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate weighted by a factor + function weightedApr() external view override returns (uint256) { + uint256 a = _apr(); + return a * _nav(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate after a new deposit + /// @param extraAmount The amount to add to the lending platform + function aprAfterDeposit(uint256 extraAmount) external view override returns (uint256) { + // i need to calculate new supplyRate after Deposit (when deposit has not been done yet) + DataTypes.ReserveData memory reserveData = _lendingPool().getReserveData(address(want)); + + ( + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + , + , + , + uint256 averageStableBorrowRate, + , + , + + ) = protocolDataProvider.getReserveData(address(want)); + + uint256 newLiquidity = availableLiquidity + extraAmount; + + (, , , , uint256 reserveFactor, , , , , ) = protocolDataProvider.getReserveConfigurationData(address(want)); + + (uint256 newLiquidityRate, , ) = IReserveInterestRateStrategy(reserveData.interestRateStrategyAddress) + .calculateInterestRates( + address(want), + newLiquidity, + totalStableDebt, + totalVariableDebt, + averageStableBorrowRate, + reserveFactor + ); + uint256 incentivesRate = _incentivesRate(newLiquidity + totalStableDebt + totalVariableDebt); // total supplied liquidity in Aave v2 + + return newLiquidityRate / 1e9 + incentivesRate; // divided by 1e9 to go from Ray to Wad + } + + /// @notice Checks if assets are currently managed by this contract + function hasAssets() external view override returns (bool) { + return aToken.balanceOf(address(this)) > 0; + } + + /// @notice Checks if harvest is callable + function harvestTrigger() external view returns (bool) { + return _checkCooldown(); + } + + // ============================= Internal Functions ============================= + + /// @notice See `apr` + function _apr() internal view returns (uint256) { + uint256 liquidityRate = uint256(_lendingPool().getReserveData(address(want)).currentLiquidityRate) / 1e9; // dividing by 1e9 to pass from ray to wad + ( + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + , + , + , + , + , + , + + ) = protocolDataProvider.getReserveData(address(want)); + uint256 incentivesRate = _incentivesRate(availableLiquidity + totalStableDebt + totalVariableDebt); // total supplied liquidity in Aave v2 + return liquidityRate + incentivesRate; + } + + /// @notice See `nav` + function _nav() internal view returns (uint256) { + return want.balanceOf(address(this)) + underlyingBalanceStored(); + } + + /// @notice See `withdraw` + function _withdraw(uint256 amount) internal returns (uint256) { + uint256 balanceUnderlying = aToken.balanceOf(address(this)); + uint256 looseBalance = want.balanceOf(address(this)); + uint256 total = balanceUnderlying + looseBalance; + + if (amount > total) { + //cant withdraw more than we own + amount = total; + } + + if (looseBalance >= amount) { + want.safeTransfer(address(strategy), amount); + return amount; + } + + //not state changing but OK because of previous call + uint256 liquidity = want.balanceOf(address(aToken)); + + if (liquidity > 1) { + uint256 toWithdraw = amount - looseBalance; + + if (toWithdraw <= liquidity) { + //we can take all + _lendingPool().withdraw(address(want), toWithdraw, address(this)); + } else { + //take all we can + _lendingPool().withdraw(address(want), liquidity, address(this)); + } + } + looseBalance = want.balanceOf(address(this)); + want.safeTransfer(address(strategy), looseBalance); + return looseBalance; + } + + /// @notice See `deposit` + function _deposit(uint256 amount) internal { + ILendingPool lp = _lendingPool(); + // NOTE: Checks if allowance is enough and acts accordingly + // allowance might not be enough if + // i) initial allowance has been used (should take years) + // ii) lendingPool contract address has changed (Aave updated the contract address) + if (want.allowance(address(this), address(lp)) < amount) { + IERC20(address(want)).safeApprove(address(lp), 0); + IERC20(address(want)).safeApprove(address(lp), type(uint256).max); + } + + uint16 referral; + uint16 __customReferral = _customReferral; + if (__customReferral != 0) { + referral = __customReferral; + } else { + referral = _DEFAULT_REFERRAL; + } + + lp.deposit(address(want), amount, address(this), referral); + } + + /// @notice Returns address of lending pool from Aave's address provider + function _lendingPool() internal view returns (ILendingPool lendingPool) { + lendingPool = ILendingPool(protocolDataProvider.ADDRESSES_PROVIDER().getLendingPool()); + } + + /// @notice Checks if there is a need for calling harvest + function _checkCooldown() internal view returns (bool) { + if (!isIncentivised) { + return false; + } + + uint256 cooldownStartTimestamp = IStakedAave(stkAave).stakersCooldowns(address(this)); + uint256 cooldownSeconds = IStakedAave(stkAave).COOLDOWN_SECONDS(); + uint256 unstakeWindow = IStakedAave(stkAave).UNSTAKE_WINDOW(); + if (block.timestamp >= cooldownStartTimestamp + cooldownSeconds) { + return + block.timestamp - cooldownStartTimestamp + cooldownSeconds <= unstakeWindow || + cooldownStartTimestamp == 0; + } else { + return false; + } + } + + /// @notice Calculates APR from Liquidity Mining Program + /// @param totalLiquidity Total liquidity available in the pool + /// @dev At Angle, compared with Yearn implementation, we have decided to add a check + /// about the `totalLiquidity` before entering the `if` branch + function _incentivesRate(uint256 totalLiquidity) internal view returns (uint256) { + // only returns != 0 if the incentives are in place at the moment. + // it will fail if the isIncentivised is set to true but there is no incentives + IAaveIncentivesController incentivesController = _incentivesController(); + if (isIncentivised && block.timestamp < incentivesController.getDistributionEnd() && totalLiquidity > 0) { + uint256 _emissionsPerSecond; + (, _emissionsPerSecond, ) = _incentivesController().getAssetData(address(aToken)); + if (_emissionsPerSecond > 0) { + uint256 emissionsInWant = _AAVEtoWant(_emissionsPerSecond); // amount of emissions in want + + uint256 incentivesRate = (emissionsInWant * _SECONDS_IN_YEAR * 1e18) / totalLiquidity; // APRs are in 1e18 + + return (incentivesRate * 9500) / 10000; // 95% of estimated APR to avoid overestimations + } + } + return 0; + } + + /// @notice Estimates the value of `_amount` AAVE tokens + /// @param _amount Amount of AAVE to compute the `want` price of + /// @dev This function uses a UniswapV2 oracle to easily compute the price (which is not feasible + /// with UniswapV3) + ///@dev When entering this function, it has been checked that the `amount` parameter is not null + // solhint-disable-next-line func-name-mixedcase + function _AAVEtoWant(uint256 _amount) internal view returns (uint256) { + // We use a different path when trying to get the price of the AAVE in `want` + address[] memory pathPrice; + + if (address(want) == address(WETH)) { + pathPrice = new address[](2); + pathPrice[0] = address(aave); + pathPrice[1] = address(want); + } else { + pathPrice = new address[](3); + pathPrice[0] = address(aave); + pathPrice[1] = address(WETH); + pathPrice[2] = address(want); + } + + uint256[] memory amounts = uniswapV2Router.getAmountsOut(_amount, pathPrice); + return amounts[amounts.length - 1]; + } + + /// @notice Swaps an amount from `AAVE` to Want + /// @param _amount The amount to convert + function _sellAAVEForWant(uint256 _amount) internal { + if (_amount == 0) { + return; + } + + if (IERC20(aave).allowance(address(this), address(uniswapV3Router)) < _amount) { + IERC20(aave).safeApprove(address(uniswapV3Router), 0); + IERC20(aave).safeApprove(address(uniswapV3Router), type(uint256).max); + } + + uniswapV3Router.exactInput(ExactInputParams(path, address(this), block.timestamp, _amount, uint256(0))); + } + + /// @notice Returns the incentive controller + function _incentivesController() internal view returns (IAaveIncentivesController) { + if (isIncentivised) { + return aToken.getIncentivesController(); + } else { + return IAaveIncentivesController(address(0)); + } + } + + /// @notice Specifies the token managed by this contract during normal operation + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](2); + protected[0] = address(want); + protected[1] = address(aToken); + return protected; + } + + // ============================= Governance ============================= + + /// @notice For the management to activate / deactivate incentives functionality + /// @param _isIncentivised Boolean for activation + function setIsIncentivised(bool _isIncentivised) external onlyRole(GUARDIAN_ROLE) { + // NOTE: if the aToken is not incentivised, `getIncentivesController()` might revert (aToken won't implement it) + // to avoid calling it, we use the OR and lazy evaluation + require( + !_isIncentivised || address(aToken.getIncentivesController()) != address(0), + "aToken does not have incentives controller set up" + ); + isIncentivised = _isIncentivised; + emit IncentivisedUpdated(_isIncentivised); + } + + /// @notice Sets the referral + /// @param __customReferral New custom referral + function setReferralCode(uint16 __customReferral) external onlyRole(GUARDIAN_ROLE) { + require(__customReferral != 0, "invalid referral code"); + _customReferral = __customReferral; + emit CustomReferralUpdated(_customReferral); + } + + /// @notice Sets the path for swap of AAVE to `want` + /// @param _path New path + function setPath(bytes memory _path) external onlyRole(GUARDIAN_ROLE) { + path = _path; + emit PathUpdated(_path); + } +} diff --git a/contracts/genericLender/GenericCompound.sol b/contracts/genericLender/GenericCompound.sol new file mode 100644 index 0000000..57a4d6d --- /dev/null +++ b/contracts/genericLender/GenericCompound.sol @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../interfaces/external/compound/CErc20I.sol"; +import "../interfaces/external/compound/IComptroller.sol"; +import "../interfaces/external/compound/InterestRateModel.sol"; +import "../interfaces/external/uniswap/IUniswapRouter.sol"; + +import "./GenericLenderBase.sol"; + +/// @title GenericCompound +/// @author Forker from here: https://github.com/Grandthrax/yearnV2-generic-lender-strat/blob/master/contracts/GenericLender/GenericCompound.sol +/// @notice A contract to lend any ERC20 to Compound +contract GenericCompound is GenericLenderBase { + using SafeERC20 for IERC20; + using Address for address; + + event PathUpdated(bytes _path); + + uint256 public constant BLOCKS_PER_YEAR = 2_350_000; + + // ==================== References to contracts ============================= + + CErc20I public immutable cToken; + address public immutable comp; + IComptroller public immutable comptroller; + IUniswapV3Router public immutable uniswapV3Router; + // Used to get the `want` price of the AAVE token + IUniswapV2Router public immutable uniswapV2Router; + + address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + + // ==================== Parameters ============================= + + bytes public path; + uint256 public minCompToSell = 0.5 ether; + + // ============================= Constructor ============================= + + /// @notice Constructor of the `GenericCompound` + /// @param _strategy Reference to the strategy using this lender + /// @param _path Bytes to encode the swap from `comp` to `want` + /// @param _cToken Address of the cToken + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + constructor( + address _strategy, + string memory name, + IUniswapV3Router _uniswapV3Router, + IUniswapV2Router _uniswapV2Router, + IComptroller _comptroller, + address _comp, + bytes memory _path, + address _cToken, + address[] memory governorList, + address guardian + ) GenericLenderBase(_strategy, name, governorList, guardian) { + // This transaction is going to revert if `_strategy`, `_comp` or `_cToken` are equal to the zero address + require( + address(_uniswapV2Router) != address(0) && + address(_uniswapV3Router) != address(0) && + address(_comptroller) != address(0), + "0" + ); + path = _path; + uniswapV3Router = _uniswapV3Router; + uniswapV2Router = _uniswapV2Router; + comptroller = _comptroller; + comp = _comp; + cToken = CErc20I(_cToken); + require(CErc20I(_cToken).underlying() == address(want), "wrong cToken"); + want.safeApprove(_cToken, type(uint256).max); + IERC20(_comp).safeApprove(address(_uniswapV3Router), type(uint256).max); + } + + // ===================== External Strategy Functions =========================== + + /// @notice Deposits the current balance of the contract to the lending platform + function deposit() external override onlyRole(STRATEGY_ROLE) { + uint256 balance = want.balanceOf(address(this)); + require(cToken.mint(balance) == 0, "mint fail"); + } + + /// @notice Withdraws a given amount from lender + /// @param amount The amount the caller wants to withdraw + /// @return Amount actually withdrawn + function withdraw(uint256 amount) external override onlyRole(STRATEGY_ROLE) returns (uint256) { + return _withdraw(amount); + } + + /// @notice Withdraws as much as possible from the lending platform + /// @return Whether everything was withdrawn or not + function withdrawAll() external override onlyRole(STRATEGY_ROLE) returns (bool) { + uint256 invested = _nav(); + uint256 returned = _withdraw(invested); + return returned >= invested; + } + + // ============================= External View Functions ============================= + + /// @notice Helper function to get the current total of assets managed by the lender. + function nav() external view override returns (uint256) { + return _nav(); + } + + /// @notice Helper function the current balance of cTokens + function underlyingBalanceStored() public view returns (uint256 balance) { + uint256 currentCr = cToken.balanceOf(address(this)); + if (currentCr == 0) { + balance = 0; + } else { + //The current exchange rate as an unsigned integer, scaled by 1e18. + balance = (currentCr * cToken.exchangeRateStored()) / 1e18; + } + } + + /// @notice Returns an estimation of the current Annual Percentage Rate + function apr() external view override returns (uint256) { + return _apr(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate weighted by a factor + function weightedApr() external view override returns (uint256) { + uint256 a = _apr(); + return a * _nav(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate after a new deposit + /// of `amount` + /// @param amount Amount to add to the lending platform, and that we want to take into account + /// in the apr computation + function aprAfterDeposit(uint256 amount) external view override returns (uint256) { + uint256 cashPrior = want.balanceOf(address(cToken)); + + uint256 borrows = cToken.totalBorrows(); + + uint256 reserves = cToken.totalReserves(); + + uint256 reserverFactor = cToken.reserveFactorMantissa(); + + InterestRateModel model = cToken.interestRateModel(); + + // The supply rate is derived from the borrow rate, reserve factor and the amount of total borrows. + uint256 supplyRate = model.getSupplyRate(cashPrior + amount, borrows, reserves, reserverFactor); + // Adding the yield from comp + return supplyRate * BLOCKS_PER_YEAR + _incentivesRate(amount); + } + + /// @notice Check if assets are currently managed by this contract + function hasAssets() external view override returns (bool) { + return cToken.balanceOf(address(this)) > 0 || want.balanceOf(address(this)) > 0; + } + + // ============================= Governance ============================= + + /// @notice Sets the path for the swap of `comp` tokens + /// @param _path New path + function setPath(bytes memory _path) external onlyRole(GUARDIAN_ROLE) { + path = _path; + emit PathUpdated(_path); + } + + /// @notice Withdraws as much as possible in case of emergency and sends it to the `PoolManager` + /// @param amount Amount to withdraw + /// @dev Does not check if any error occurs or if the amount withdrawn is correct + function emergencyWithdraw(uint256 amount) external override onlyRole(GUARDIAN_ROLE) { + // Do not care about errors here, what is important is to withdraw what is possible + cToken.redeemUnderlying(amount); + + want.safeTransfer(address(poolManager), want.balanceOf(address(this))); + } + + // ============================= Internal Functions ============================= + + /// @notice See `apr` + function _apr() internal view returns (uint256) { + return cToken.supplyRatePerBlock() * BLOCKS_PER_YEAR + _incentivesRate(0); + } + + /// @notice See `nav` + function _nav() internal view returns (uint256) { + return want.balanceOf(address(this)) + underlyingBalanceStored(); + } + + /// @notice See `withdraw` + function _withdraw(uint256 amount) internal returns (uint256) { + uint256 balanceUnderlying = cToken.balanceOfUnderlying(address(this)); + uint256 looseBalance = want.balanceOf(address(this)); + uint256 total = balanceUnderlying + looseBalance; + + if (amount > total) { + // Can't withdraw more than we own + amount = total; + } + + if (looseBalance >= amount) { + want.safeTransfer(address(strategy), amount); + return amount; + } + + // Not state changing but OK because of previous call + uint256 liquidity = want.balanceOf(address(cToken)); + + if (liquidity > 1) { + uint256 toWithdraw = amount - looseBalance; + + if (toWithdraw <= liquidity) { + // We can take all + require(cToken.redeemUnderlying(toWithdraw) == 0, "redeemUnderlying fail"); + } else { + // Take all we can + require(cToken.redeemUnderlying(liquidity) == 0, "redeemUnderlying fail"); + } + } + _disposeOfComp(); + looseBalance = want.balanceOf(address(this)); + want.safeTransfer(address(strategy), looseBalance); + return looseBalance; + } + + /// @notice Claims and swaps from Uniswap the `comp` earned + function _disposeOfComp() internal { + address[] memory holders = new address[](1); + CTokenI[] memory cTokens = new CTokenI[](1); + holders[0] = address(this); + cTokens[0] = CTokenI(address(cToken)); + comptroller.claimComp(holders, cTokens, false, true); + uint256 _comp = IERC20(comp).balanceOf(address(this)); + + if (_comp > minCompToSell) { + uniswapV3Router.exactInput(ExactInputParams(path, address(this), block.timestamp, _comp, uint256(0))); + } + } + + /// @notice Calculates APR from Compound's Liquidity Mining Program + /// @param amountToAdd Amount to add to the `totalSupplyInWant` (for the `aprAfterDeposit` function) + function _incentivesRate(uint256 amountToAdd) internal view returns (uint256) { + uint256 supplySpeed = comptroller.compSupplySpeeds(address(cToken)); + uint256 totalSupplyInWant = (cToken.totalSupply() * cToken.exchangeRateStored()) / 1e18 + amountToAdd; + // `supplySpeed` is in `COMP` unit -> the following operation is going to put it in `want` unit + supplySpeed = _comptoWant(supplySpeed); + uint256 incentivesRate; + // Added for testing purposes and to handle the edge case where there is nothing left in a market + if (totalSupplyInWant == 0) { + incentivesRate = supplySpeed * BLOCKS_PER_YEAR; + } else { + // `incentivesRate` is expressed in base 18 like all APR + incentivesRate = (supplySpeed * BLOCKS_PER_YEAR * 1e18) / totalSupplyInWant; + } + return (incentivesRate * 9500) / 10000; // 95% of estimated APR to avoid overestimations + } + + /// @notice Estimates the value of `_amount` AAVE tokens + /// @param _amount Amount of comp to compute the `want` price of + /// @dev This function uses a UniswapV2 oracle to easily compute the price (which is not feasible + /// with UniswapV3) + function _comptoWant(uint256 _amount) internal view returns (uint256) { + if (_amount == 0) { + return 0; + } + // We use a different path when trying to get the price of the AAVE in `want` + address[] memory pathPrice; + + if (address(want) == address(WETH)) { + pathPrice = new address[](2); + pathPrice[0] = address(comp); + pathPrice[1] = address(want); + } else { + pathPrice = new address[](3); + pathPrice[0] = address(comp); + pathPrice[1] = address(WETH); + pathPrice[2] = address(want); + } + + uint256[] memory amounts = uniswapV2Router.getAmountsOut(_amount, pathPrice); // APRs are in 1e18 + return amounts[amounts.length - 1]; + } + + /// @notice Specifies the token managed by this contract during normal operation + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](3); + protected[0] = address(want); + protected[1] = address(cToken); + protected[2] = comp; + return protected; + } +} diff --git a/contracts/genericLender/GenericCompoundRinkeby.sol b/contracts/genericLender/GenericCompoundRinkeby.sol new file mode 100644 index 0000000..47abd07 --- /dev/null +++ b/contracts/genericLender/GenericCompoundRinkeby.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../interfaces/external/compound/CErc20I.sol"; +import "../interfaces/external/compound/InterestRateModel.sol"; +import "../interfaces/external/uniswap/IUniswapRouter.sol"; + +import "./GenericLenderBase.sol"; + +/// @title GenericCompound +/// @author Forked from https://github.com/Grandthrax/yearnv2/blob/master/contracts/GenericDyDx/GenericCompound.sol +/// @notice A contract to lend any ERC20 to Compound +/// @dev This contract is the Rinkeby version of `GenericCompound`, it differs in the `apr` function +contract GenericCompoundRinkeby is GenericLenderBase { + using SafeERC20 for IERC20; + using Address for address; + + uint256 public constant BLOCKS_PER_YEAR = 2_300_000; + + // ==================== References to contracts ============================= + + address public uniswapRouter; + address public comp; + CErc20I public cToken; + + // ==================== Parameters ============================= + + bytes public path; + uint256 public minCompToSell = 0.5 ether; + + // ============================= Constructor ============================= + + /// @notice Constructor of the GenericLenderBase + /// @param _strategy Reference to the strategy using this lender + /// @param _uniswapRouter Uniswap router interface to swap reward tokens + /// @param _comp Address of the comp token + /// @param _path Bytes to encode the swap from comp to want + /// @param _cToken Address of the cToken + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + constructor( + address _strategy, + string memory name, + address _uniswapRouter, + address _comp, + bytes memory _path, + address _cToken, + address[] memory governorList, + address guardian + ) GenericLenderBase(_strategy, name, governorList, guardian) { + require(address(_comp) != address(0) && address(_strategy) != address(0), "0"); + uniswapRouter = _uniswapRouter; + comp = _comp; + path = _path; + cToken = CErc20I(_cToken); + require(cToken.underlying() == address(want), "wrong cToken"); + want.safeApprove(_cToken, type(uint256).max); + IERC20(comp).safeApprove(address(_uniswapRouter), type(uint256).max); + } + + // ===================== External Strategy Functions =========================== + + /// @notice Deposits the current balance to the lending platform + function deposit() external override onlyRole(STRATEGY_ROLE) { + uint256 balance = want.balanceOf(address(this)); + require(cToken.mint(balance) == 0, "mint fail"); + } + + /// @notice Withdraws a given amount from lender + /// @param amount The amount the caller wants to withdraw + /// @return The amounts actually withdrawn + function withdraw(uint256 amount) external override onlyRole(STRATEGY_ROLE) returns (uint256) { + return _withdraw(amount); + } + + /// @notice Withdraws as much as possible + /// @return Whether everything was withdrawn or not + function withdrawAll() external override onlyRole(STRATEGY_ROLE) returns (bool) { + uint256 invested = _nav(); + uint256 returned = _withdraw(invested); + return returned >= invested; + } + + // ============================= External View Functions ============================= + + /// @notice Helper function to get the current total of assets managed by the lender. + function nav() external view override returns (uint256) { + return _nav(); + } + + /// @notice Helper function the current balance of cTokens + function underlyingBalanceStored() public view returns (uint256 balance) { + uint256 currentCr = cToken.balanceOf(address(this)); + if (currentCr == 0) { + balance = 0; + } else { + //The current exchange rate as an unsigned integer, scaled by 1e18. + balance = (currentCr * cToken.exchangeRateStored()) / 1e18; + } + } + + /// @notice Returns an estimation of the current Annual Percentage Rate + function apr() external view override returns (uint256) { + return _apr(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate weighted by a factor + function weightedApr() external view override returns (uint256) { + uint256 a = _apr(); + return a * _nav(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate after a new deposit + /// @param amount The amount to add to the lending platform + // solhint-disable-next-line no-unused-vars + function aprAfterDeposit(uint256 amount) external view override returns (uint256) { + // Rinkeby version + return _apr(); + } + + /// @notice Check if any assets is currently managed by this contract + function hasAssets() external view override returns (bool) { + return cToken.balanceOf(address(this)) > 0 || want.balanceOf(address(this)) > 0; + } + + // ============================= Governance ============================= + + /// @notice Sets the path for the swap of COMP tokens + /// @param _path New path + function setPath(bytes memory _path) external onlyRole(GUARDIAN_ROLE) { + path = _path; + } + + /// @notice Withdraws as much as possible in case of emergency and sends it to the poolManager + /// @param amount Amount to withdraw + /// @dev Does not check if any error occurs or the amount withdrawn + function emergencyWithdraw(uint256 amount) external override onlyRole(GUARDIAN_ROLE) { + // Don't care about errors here. we want to exit what we can + cToken.redeemUnderlying(amount); + + want.safeTransfer(address(poolManager), want.balanceOf(address(this))); + } + + // ============================= Internal Functions ============================= + + /// @notice See 'apr' + function _apr() internal view returns (uint256) { + return cToken.supplyRatePerBlock() * BLOCKS_PER_YEAR; + } + + /// @notice See 'nav' + function _nav() internal view returns (uint256) { + return want.balanceOf(address(this)) + underlyingBalanceStored(); + } + + /// @notice See 'withdraw' + function _withdraw(uint256 amount) internal returns (uint256) { + uint256 balanceUnderlying = cToken.balanceOfUnderlying(address(this)); + uint256 looseBalance = want.balanceOf(address(this)); + uint256 total = balanceUnderlying + looseBalance; + + if (amount > total) { + //cant withdraw more than we own + amount = total; + } + + if (looseBalance >= amount) { + want.safeTransfer(address(strategy), amount); + return amount; + } + + //not state changing but OK because of previous call + uint256 liquidity = want.balanceOf(address(cToken)); + + if (liquidity > 1) { + uint256 toWithdraw = amount - looseBalance; + + if (toWithdraw <= liquidity) { + //we can take all + require(cToken.redeemUnderlying(toWithdraw) == 0, "redeemUnderlying fail"); + } else { + //take all we can + require(cToken.redeemUnderlying(liquidity) == 0, "redeemUnderlying fail"); + } + } + _disposeOfComp(); + looseBalance = want.balanceOf(address(this)); + want.safeTransfer(address(strategy), looseBalance); + return looseBalance; + } + + /// @notice Claims and swaps to Uniswap the Comp earned + function _disposeOfComp() internal { + uint256 _comp = IERC20(comp).balanceOf(address(this)); + + if (_comp > minCompToSell) { + IUniswapV3Router(uniswapRouter).exactInput( + ExactInputParams(path, address(this), block.timestamp, _comp, uint256(0)) + ); + } + } + + /// @notice Specifies the token managed by this contract during normal operation + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](3); + protected[0] = address(want); + protected[1] = address(cToken); + protected[2] = comp; + return protected; + } +} diff --git a/contracts/genericLender/GenericCompoundRinkebyETH.sol b/contracts/genericLender/GenericCompoundRinkebyETH.sol new file mode 100644 index 0000000..ebba15d --- /dev/null +++ b/contracts/genericLender/GenericCompoundRinkebyETH.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../interfaces/external/compound/CEtherI.sol"; +import "../interfaces/external/compound/InterestRateModel.sol"; +import "../interfaces/external/uniswap/IUniswapRouter.sol"; + +import "./GenericLenderBase.sol"; + +interface IWETH is IERC20 { + function withdraw(uint256 wad) external; + + function deposit() external payable; +} + +/// @title GenericCompound +/// @author Forked from https://github.com/Grandthrax/yearnv2/blob/master/contracts/GenericDyDx/GenericCompound.sol +/// @notice A contract to lend any ERC20 to Compound +/// @dev This contract is the Rinkeby version of `GenericCompound`, it differs in the `apr` function +contract GenericCompoundRinkebyETH is GenericLenderBase { + using SafeERC20 for IERC20; + using Address for address; + + uint256 public constant BLOCKS_PER_YEAR = 2_300_000; + + // ==================== References to contracts ============================= + + address public uniswapRouter; + address public comp; + CEtherI public cToken; + + // ==================== Parameters ============================= + + bytes public path; + uint256 public minCompToSell = 0.5 ether; + + // ============================= Constructor ============================= + + /// @notice Constructor of the GenericLenderBase + /// @param _strategy Reference to the strategy using this lender + /// @param _uniswapRouter Uniswap router interface to swap reward tokens + /// @param _comp Address of the comp token + /// @param _path Bytes to encode the swap from comp to want + /// @param _cToken Address of the cToken + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + constructor( + address _strategy, + string memory name, + address _uniswapRouter, + address _comp, + bytes memory _path, + address _cToken, + address[] memory governorList, + address guardian + ) GenericLenderBase(_strategy, name, governorList, guardian) { + require(address(_comp) != address(0) && address(_strategy) != address(0), "0"); + uniswapRouter = _uniswapRouter; + comp = _comp; + path = _path; + cToken = CEtherI(_cToken); + IERC20(comp).safeApprove(address(_uniswapRouter), type(uint256).max); + } + + // ===================== External Strategy Functions =========================== + + /// @notice Deposits the current balance to the lending platform + function deposit() external override onlyRole(STRATEGY_ROLE) { + uint256 balance = IWETH(address(want)).balanceOf(address(this)); + IWETH(address(want)).withdraw(balance); + cToken.mint{ value: balance }(); + } + + /// @notice Withdraws a given amount from lender + /// @param amount The amount the caller wants to withdraw + /// @return The amounts actually withdrawn + function withdraw(uint256 amount) external override onlyRole(STRATEGY_ROLE) returns (uint256) { + return _withdraw(amount); + } + + /// @notice Withdraws as much as possible + /// @return Whether everything was withdrawn or not + function withdrawAll() external override onlyRole(STRATEGY_ROLE) returns (bool) { + uint256 invested = _nav(); + uint256 returned = _withdraw(invested); + return returned >= invested; + } + + // ============================= External View Functions ============================= + + /// @notice Helper function to get the current total of assets managed by the lender. + function nav() external view override returns (uint256) { + return _nav(); + } + + /// @notice Helper function the current balance of cTokens + function underlyingBalanceStored() public view returns (uint256 balance) { + uint256 currentCr = cToken.balanceOf(address(this)); + if (currentCr == 0) { + balance = 0; + } else { + //The current exchange rate as an unsigned integer, scaled by 1e18. + balance = (currentCr * cToken.exchangeRateStored()) / 1e18; + } + } + + /// @notice Returns an estimation of the current Annual Percentage Rate + function apr() external view override returns (uint256) { + return _apr(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate weighted by a factor + function weightedApr() external view override returns (uint256) { + uint256 a = _apr(); + return a * _nav(); + } + + /// @notice Returns an estimation of the current Annual Percentage Rate after a new deposit + /// @param amount The amount to add to the lending platform + // solhint-disable-next-line no-unused-vars + function aprAfterDeposit(uint256 amount) external view override returns (uint256) { + // Rinkeby version + return _apr(); + } + + /// @notice Check if any assets is currently managed by this contract + function hasAssets() external view override returns (bool) { + return cToken.balanceOf(address(this)) > 0 || IWETH(address(want)).balanceOf(address(this)) > 0; + } + + // ============================= Governance ============================= + + /// @notice Sets the path for the swap of COMP tokens + /// @param _path New path + function setPath(bytes memory _path) external onlyRole(GUARDIAN_ROLE) { + path = _path; + } + + /// @notice Withdraws as much as possible in case of emergency and sends it to the poolManager + /// @param amount Amount to withdraw + /// @dev Does not check if any error occurs or the amount withdrawn + function emergencyWithdraw(uint256 amount) external override onlyRole(GUARDIAN_ROLE) { + // Don't care about errors here. we want to exit what we can + cToken.redeemUnderlying(amount); + IWETH(address(want)).withdraw(address(this).balance); + want.safeTransfer(address(poolManager), IWETH(address(want)).balanceOf(address(this))); + } + + // ============================= Internal Functions ============================= + + /// @notice See 'apr' + function _apr() internal view returns (uint256) { + return cToken.supplyRatePerBlock() * BLOCKS_PER_YEAR; + } + + /// @notice See 'nav' + function _nav() internal view returns (uint256) { + return IWETH(address(want)).balanceOf(address(this)) + underlyingBalanceStored(); + } + + /// @notice See 'withdraw' + function _withdraw(uint256 amount) internal returns (uint256) { + uint256 balanceUnderlying = cToken.balanceOfUnderlying(address(this)); + uint256 looseBalance = IWETH(address(want)).balanceOf(address(this)); + uint256 total = balanceUnderlying + looseBalance; + + if (amount > total) { + //cant withdraw more than we own + amount = total; + } + + if (looseBalance >= amount) { + want.safeTransfer(address(strategy), amount); + return amount; + } + + //not state changing but OK because of previous call + uint256 liquidity = want.balanceOf(address(cToken)); + + if (liquidity > 1) { + uint256 toWithdraw = amount - looseBalance; + + if (toWithdraw <= liquidity) { + //we can take all + require(cToken.redeemUnderlying(toWithdraw) == 0, "redeemUnderlying fail"); + IWETH(address(want)).deposit{ value: address(this).balance }(); + } else { + //take all we can + require(cToken.redeemUnderlying(liquidity) == 0, "redeemUnderlying fail"); + IWETH(address(want)).deposit{ value: address(this).balance }(); + } + } + _disposeOfComp(); + looseBalance = want.balanceOf(address(this)); + want.safeTransfer(address(strategy), looseBalance); + return looseBalance; + } + + /// @notice Claims and swaps to Uniswap the Comp earned + function _disposeOfComp() internal { + uint256 _comp = IERC20(comp).balanceOf(address(this)); + + if (_comp > minCompToSell) { + IUniswapV3Router(uniswapRouter).exactInput( + ExactInputParams(path, address(this), block.timestamp, _comp, uint256(0)) + ); + } + } + + /// @notice Specifies the token managed by this contract during normal operation + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](3); + protected[0] = address(want); + protected[1] = address(cToken); + protected[2] = comp; + return protected; + } + + /// @notice In case ETH is required for some transactions + receive() external payable {} +} diff --git a/contracts/genericLender/GenericLenderBase.sol b/contracts/genericLender/GenericLenderBase.sol new file mode 100644 index 0000000..18a3ed1 --- /dev/null +++ b/contracts/genericLender/GenericLenderBase.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +import "../external/AccessControl.sol"; + +import "../interfaces/IGenericLender.sol"; +import "../interfaces/IPoolManager.sol"; +import "../interfaces/IStrategy.sol"; + +/// @title GenericLenderBase +/// @author Forked from https://github.com/Grandthrax/yearnV2-generic-lender-strat/tree/master/contracts/GenericLender +/// @notice A base contract to build contracts to lend assets +abstract contract GenericLenderBase is IGenericLender, AccessControl { + using SafeERC20 for IERC20; + + bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); + bytes32 public constant STRATEGY_ROLE = keccak256("STRATEGY_ROLE"); + + string public override lenderName; + + // ============================= References to contracts ============================= + + /// @notice Reference to the protocol's collateral poolManager + IPoolManager public poolManager; + + /// @notice Reference to the `Strategy` + address public override strategy; + + /// @notice Reference to the token lent + IERC20 public want; + + // ============================= Constructor ============================= + + /// @notice Constructor of the `GenericLenderBase` + /// @param _strategy Reference to the strategy using this lender + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + constructor( + address _strategy, + string memory _name, + address[] memory governorList, + address guardian + ) { + strategy = _strategy; + // The corresponding `PoolManager` is inferred from the `Strategy` + poolManager = IPoolManager(IStrategy(strategy).poolManager()); + want = IERC20(poolManager.token()); + lenderName = _name; + + _setupRole(GUARDIAN_ROLE, address(poolManager)); + for (uint256 i = 0; i < governorList.length; i++) { + _setupRole(GUARDIAN_ROLE, governorList[i]); + } + _setupRole(GUARDIAN_ROLE, guardian); + _setupRole(STRATEGY_ROLE, _strategy); + _setRoleAdmin(GUARDIAN_ROLE, STRATEGY_ROLE); + _setRoleAdmin(STRATEGY_ROLE, GUARDIAN_ROLE); + + want.safeApprove(_strategy, type(uint256).max); + } + + // ============================= Governance ============================= + + /// @notice Override this to add all tokens/tokenized positions this contract + /// manages on a *persistent* basis (e.g. not just for swapping back to + /// want ephemerally). + /// + /// Example: + /// ``` + /// function _protectedTokens() internal override view returns (address[] memory) { + /// address[] memory protected = new address[](3); + /// protected[0] = tokenA; + /// protected[1] = tokenB; + /// protected[2] = tokenC; + /// return protected; + /// } + /// ``` + function _protectedTokens() internal view virtual returns (address[] memory); + + /// @notice + /// Removes tokens from this Strategy that are not the type of tokens + /// managed by this Strategy. This may be used in case of accidentally + /// sending the wrong kind of token to this Strategy. + /// + /// Tokens will be sent to `governance()`. + /// + /// This will fail if an attempt is made to sweep `want`, or any tokens + /// that are protected by this Strategy. + /// + /// This may only be called by governance. + /// @param _token The token to transfer out of this poolManager. + /// @param to Address to send the tokens to. + /// @dev + /// Implement `_protectedTokens()` to specify any additional tokens that + /// should be protected from sweeping in addition to `want`. + function sweep(address _token, address to) external override onlyRole(GUARDIAN_ROLE) { + address[] memory __protectedTokens = _protectedTokens(); + for (uint256 i = 0; i < __protectedTokens.length; i++) require(_token != __protectedTokens[i], "93"); + + IERC20(_token).safeTransfer(to, IERC20(_token).balanceOf(address(this))); + } +} diff --git a/contracts/interfaces/IAccessControl.sol b/contracts/interfaces/IAccessControl.sol new file mode 100644 index 0000000..caf7936 --- /dev/null +++ b/contracts/interfaces/IAccessControl.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title IAccessControl +/// @author Forked from OpenZeppelin +/// @notice Interface for `AccessControl` contracts +interface IAccessControl { + function hasRole(bytes32 role, address account) external view returns (bool); + + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + function grantRole(bytes32 role, address account) external; + + function revokeRole(bytes32 role, address account) external; + + function renounceRole(bytes32 role, address account) external; +} diff --git a/contracts/interfaces/IAgToken.sol b/contracts/interfaces/IAgToken.sol new file mode 100644 index 0000000..f0d3a18 --- /dev/null +++ b/contracts/interfaces/IAgToken.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; + +/// @title IAgToken +/// @author Angle Core Team +/// @notice Interface for the stablecoins `AgToken` contracts +/// @dev The only functions that are left in the interface are the functions which are used +/// at another point in the protocol by a different contract +interface IAgToken is IERC20Upgradeable { + // ======================= `StableMaster` functions ============================ + function mint(address account, uint256 amount) external; + + function burnFrom( + uint256 amount, + address burner, + address sender + ) external; + + function burnSelf(uint256 amount, address burner) external; + + // ========================= External function ================================= + + function stableMaster() external view returns (address); +} diff --git a/contracts/interfaces/IAngleDistributor.sol b/contracts/interfaces/IAngleDistributor.sol new file mode 100644 index 0000000..6ef0a3a --- /dev/null +++ b/contracts/interfaces/IAngleDistributor.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/// @title IAngleDistributor +/// @author Angle Core Team +/// @notice Interface for the `AngleDistributor` contract +interface IAngleDistributor { + function rewardToken() external view returns (IERC20); + + function delegateGauge() external view returns (address); +} diff --git a/contracts/interfaces/IAngleMiddlemanGauge.sol b/contracts/interfaces/IAngleMiddlemanGauge.sol new file mode 100644 index 0000000..5907a6c --- /dev/null +++ b/contracts/interfaces/IAngleMiddlemanGauge.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title IAngleMiddlemanGauge +/// @author Angle Core Team +/// @notice Interface for the `AngleMiddleman` contract +interface IAngleMiddlemanGauge { + function notifyReward(address gauge, uint256 amount) external; +} diff --git a/contracts/interfaces/IBondingCurve.sol b/contracts/interfaces/IBondingCurve.sol new file mode 100644 index 0000000..2662d2f --- /dev/null +++ b/contracts/interfaces/IBondingCurve.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IAgToken.sol"; +import "./IOracle.sol"; + +/// @title IBondingCurve +/// @author Angle Core Team +/// @notice Interface for the `BondingCurve` contract +interface IBondingCurve { + // ============================ User Functions ================================= + + function buySoldToken( + IAgToken _agToken, + uint256 targetSoldTokenQuantity, + uint256 maxAmountToPayInAgToken + ) external; + + // ========================== Governance Functions ============================= + + function changeOracle(IAgToken _agToken, IOracle _oracle) external; +} diff --git a/contracts/interfaces/ICollateralSettler.sol b/contracts/interfaces/ICollateralSettler.sol new file mode 100644 index 0000000..3293462 --- /dev/null +++ b/contracts/interfaces/ICollateralSettler.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title ICollateralSettler +/// @author Angle Core Team +/// @notice Interface for the collateral settlement contracts +interface ICollateralSettler { + function triggerSettlement( + uint256 _oracleValue, + uint256 _sanRate, + uint256 _stocksUsers + ) external; +} diff --git a/contracts/interfaces/ICore.sol b/contracts/interfaces/ICore.sol new file mode 100644 index 0000000..0d9fb94 --- /dev/null +++ b/contracts/interfaces/ICore.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IStableMaster.sol"; + +/// @title ICore +/// @author Angle Core Team +/// @dev Interface for the functions of the `Core` contract +interface ICore { + function revokeStableMaster(address stableMaster) external; + + function addGovernor(address _governor) external; + + function removeGovernor(address _governor) external; + + function setGuardian(address _guardian) external; + + function revokeGuardian() external; + + function governorList() external view returns (address[] memory); + + function stablecoinList() external view returns (address[] memory); + + function guardian() external view returns (address); +} diff --git a/contracts/interfaces/IERC721.sol b/contracts/interfaces/IERC721.sol new file mode 100644 index 0000000..53d07cf --- /dev/null +++ b/contracts/interfaces/IERC721.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +interface IERC721 is IERC165 { + function balanceOf(address owner) external view returns (uint256 balance); + + function ownerOf(uint256 tokenId) external view returns (address owner); + + function safeTransferFrom( + address from, + address to, + uint256 tokenId + ) external; + + function transferFrom( + address from, + address to, + uint256 tokenId + ) external; + + function approve(address to, uint256 tokenId) external; + + function getApproved(uint256 tokenId) external view returns (address operator); + + function setApprovalForAll(address operator, bool _approved) external; + + function isApprovedForAll(address owner, address operator) external view returns (bool); + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; +} + +interface IERC721Metadata is IERC721 { + function name() external view returns (string memory); + + function symbol() external view returns (string memory); + + function tokenURI(uint256 tokenId) external view returns (string memory); +} diff --git a/contracts/interfaces/IFeeDistributor.sol b/contracts/interfaces/IFeeDistributor.sol new file mode 100644 index 0000000..65aab72 --- /dev/null +++ b/contracts/interfaces/IFeeDistributor.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title IFeeDistributor +/// @author Interface of the `FeeDistributor` contract +/// @dev This interface is used by the `SurplusConverter` contract to send funds to the `FeeDistributor` +interface IFeeDistributor { + function burn(address token) external; +} diff --git a/contracts/interfaces/IFeeManager.sol b/contracts/interfaces/IFeeManager.sol new file mode 100644 index 0000000..afe30cc --- /dev/null +++ b/contracts/interfaces/IFeeManager.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IAccessControl.sol"; + +/// @title IFeeManagerFunctions +/// @author Angle Core Team +/// @dev Interface for the `FeeManager` contract +interface IFeeManagerFunctions is IAccessControl { + // ================================= Keepers =================================== + + function updateUsersSLP() external; + + function updateHA() external; + + // ================================= Governance ================================ + + function deployCollateral( + address[] memory governorList, + address guardian, + address _perpetualManager + ) external; + + function setFees( + uint256[] memory xArray, + uint64[] memory yArray, + uint8 typeChange + ) external; + + function setHAFees(uint64 _haFeeDeposit, uint64 _haFeeWithdraw) external; +} + +/// @title IFeeManager +/// @author Angle Core Team +/// @notice Previous interface with additionnal getters for public variables and mappings +/// @dev We need these getters as they are used in other contracts of the protocol +interface IFeeManager is IFeeManagerFunctions { + function stableMaster() external view returns (address); + + function perpetualManager() external view returns (address); +} diff --git a/contracts/interfaces/IGaugeController.sol b/contracts/interfaces/IGaugeController.sol new file mode 100644 index 0000000..082898d --- /dev/null +++ b/contracts/interfaces/IGaugeController.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +interface IGaugeController { + //solhint-disable-next-line + function gauge_types(address addr) external view returns (int128); + + //solhint-disable-next-line + function gauge_relative_weight_write(address addr, uint256 timestamp) external returns (uint256); + + //solhint-disable-next-line + function gauge_relative_weight(address addr, uint256 timestamp) external view returns (uint256); +} diff --git a/contracts/interfaces/IGenericLender.sol b/contracts/interfaces/IGenericLender.sol new file mode 100644 index 0000000..e875c00 --- /dev/null +++ b/contracts/interfaces/IGenericLender.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IAccessControl.sol"; + +/// @title IGenericLender +/// @author Yearn with slight modifications from Angle Core Team +/// @dev Interface for the `GenericLender` contract, the base interface for contracts interacting +/// with lending and yield farming platforms +interface IGenericLender is IAccessControl { + function lenderName() external view returns (string memory); + + function nav() external view returns (uint256); + + function strategy() external view returns (address); + + function apr() external view returns (uint256); + + function weightedApr() external view returns (uint256); + + function withdraw(uint256 amount) external returns (uint256); + + function emergencyWithdraw(uint256 amount) external; + + function deposit() external; + + function withdrawAll() external returns (bool); + + function hasAssets() external view returns (bool); + + function aprAfterDeposit(uint256 amount) external view returns (uint256); + + function sweep(address _token, address to) external; +} diff --git a/contracts/interfaces/ILiquidityGauge.sol b/contracts/interfaces/ILiquidityGauge.sol new file mode 100644 index 0000000..749fbf4 --- /dev/null +++ b/contracts/interfaces/ILiquidityGauge.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +interface ILiquidityGauge { + // solhint-disable-next-line + function deposit_reward_token(address _rewardToken, uint256 _amount) external; +} diff --git a/contracts/interfaces/IOracle.sol b/contracts/interfaces/IOracle.sol new file mode 100644 index 0000000..a95bf60 --- /dev/null +++ b/contracts/interfaces/IOracle.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title IOracle +/// @author Angle Core Team +/// @notice Interface for Angle's oracle contracts reading oracle rates from both UniswapV3 and Chainlink +/// from just UniswapV3 or from just Chainlink +interface IOracle { + function read() external view returns (uint256); + + function readAll() external view returns (uint256 lowerRate, uint256 upperRate); + + function readLower() external view returns (uint256); + + function readUpper() external view returns (uint256); + + function readQuote(uint256 baseAmount) external view returns (uint256); + + function readQuoteLower(uint256 baseAmount) external view returns (uint256); + + function inBase() external view returns (uint256); +} diff --git a/contracts/interfaces/IPerpetualManager.sol b/contracts/interfaces/IPerpetualManager.sol new file mode 100644 index 0000000..131c282 --- /dev/null +++ b/contracts/interfaces/IPerpetualManager.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IERC721.sol"; +import "./IFeeManager.sol"; +import "./IOracle.sol"; +import "./IAccessControl.sol"; + +/// @title Interface of the contract managing perpetuals +/// @author Angle Core Team +/// @dev Front interface, meaning only user-facing functions +interface IPerpetualManagerFront is IERC721Metadata { + function openPerpetual( + address owner, + uint256 amountBrought, + uint256 amountCommitted, + uint256 maxOracleRate, + uint256 minNetMargin + ) external returns (uint256 perpetualID); + + function closePerpetual( + uint256 perpetualID, + address to, + uint256 minCashOutAmount + ) external; + + function addToPerpetual(uint256 perpetualID, uint256 amount) external; + + function removeFromPerpetual( + uint256 perpetualID, + uint256 amount, + address to + ) external; + + function liquidatePerpetuals(uint256[] memory perpetualIDs) external; + + function forceClosePerpetuals(uint256[] memory perpetualIDs) external; + + // ========================= External View Functions ============================= + + function getCashOutAmount(uint256 perpetualID, uint256 rate) external view returns (uint256, uint256); + + function isApprovedOrOwner(address spender, uint256 perpetualID) external view returns (bool); +} + +/// @title Interface of the contract managing perpetuals +/// @author Angle Core Team +/// @dev This interface does not contain user facing functions, it just has functions that are +/// interacted with in other parts of the protocol +interface IPerpetualManagerFunctions is IAccessControl { + // ================================= Governance ================================ + + function deployCollateral( + address[] memory governorList, + address guardian, + IFeeManager feeManager, + IOracle oracle_ + ) external; + + function setFeeManager(IFeeManager feeManager_) external; + + function setHAFees( + uint64[] memory _xHAFees, + uint64[] memory _yHAFees, + uint8 deposit + ) external; + + function setTargetAndLimitHAHedge(uint64 _targetHAHedge, uint64 _limitHAHedge) external; + + function setKeeperFeesLiquidationRatio(uint64 _keeperFeesLiquidationRatio) external; + + function setKeeperFeesCap(uint256 _keeperFeesLiquidationCap, uint256 _keeperFeesClosingCap) external; + + function setKeeperFeesClosing(uint64[] memory _xKeeperFeesClosing, uint64[] memory _yKeeperFeesClosing) external; + + function setLockTime(uint64 _lockTime) external; + + function setBoundsPerpetual(uint64 _maxLeverage, uint64 _maintenanceMargin) external; + + function pause() external; + + function unpause() external; + + // ==================================== Keepers ================================ + + function setFeeKeeper(uint64 feeDeposit, uint64 feesWithdraw) external; + + // =============================== StableMaster ================================ + + function setOracle(IOracle _oracle) external; +} + +/// @title IPerpetualManager +/// @author Angle Core Team +/// @notice Previous interface with additionnal getters for public variables +interface IPerpetualManager is IPerpetualManagerFunctions { + function poolManager() external view returns (address); + + function oracle() external view returns (address); + + function targetHAHedge() external view returns (uint64); + + function totalHedgeAmount() external view returns (uint256); +} diff --git a/contracts/interfaces/IPoolManager.sol b/contracts/interfaces/IPoolManager.sol new file mode 100644 index 0000000..2d7757e --- /dev/null +++ b/contracts/interfaces/IPoolManager.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IFeeManager.sol"; +import "./IPerpetualManager.sol"; +import "./IOracle.sol"; + +// Struct for the parameters associated to a strategy interacting with a collateral `PoolManager` +// contract +struct StrategyParams { + // Timestamp of last report made by this strategy + // It is also used to check if a strategy has been initialized + uint256 lastReport; + // Total amount the strategy is expected to have + uint256 totalStrategyDebt; + // The share of the total assets in the `PoolManager` contract that the `strategy` can access to. + uint256 debtRatio; +} + +/// @title IPoolManagerFunctions +/// @author Angle Core Team +/// @notice Interface for the collateral poolManager contracts handling each one type of collateral for +/// a given stablecoin +/// @dev Only the functions used in other contracts of the protocol are left here +interface IPoolManagerFunctions { + // ============================ Constructor ==================================== + + function deployCollateral( + address[] memory governorList, + address guardian, + IPerpetualManager _perpetualManager, + IFeeManager feeManager, + IOracle oracle + ) external; + + // ============================ Yield Farming ================================== + + function creditAvailable() external view returns (uint256); + + function debtOutstanding() external view returns (uint256); + + function report( + uint256 _gain, + uint256 _loss, + uint256 _debtPayment + ) external; + + // ============================ Governance ===================================== + + function addGovernor(address _governor) external; + + function removeGovernor(address _governor) external; + + function setGuardian(address _guardian, address guardian) external; + + function revokeGuardian(address guardian) external; + + function setFeeManager(IFeeManager _feeManager) external; + + // ============================= Getters ======================================= + + function getBalance() external view returns (uint256); + + function getTotalAsset() external view returns (uint256); +} + +/// @title IPoolManager +/// @author Angle Core Team +/// @notice Previous interface with additionnal getters for public variables and mappings +/// @dev Used in other contracts of the protocol +interface IPoolManager is IPoolManagerFunctions { + function stableMaster() external view returns (address); + + function perpetualManager() external view returns (address); + + function token() external view returns (address); + + function feeManager() external view returns (address); + + function totalDebt() external view returns (uint256); + + function strategies(address _strategy) external view returns (StrategyParams memory); +} diff --git a/contracts/interfaces/IRewardsDistributor.sol b/contracts/interfaces/IRewardsDistributor.sol new file mode 100644 index 0000000..4eb3c62 --- /dev/null +++ b/contracts/interfaces/IRewardsDistributor.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "./IStakingRewards.sol"; + +/// @title IRewardsDistributor +/// @author Angle Core Team, inspired from Fei protocol +/// (https://github.com/fei-protocol/fei-protocol-core/blob/master/contracts/staking/IRewardsDistributor.sol) +/// @notice Rewards Distributor interface +interface IRewardsDistributor { + // ========================= Public Parameter Getter =========================== + + function rewardToken() external view returns (IERC20); + + // ======================== External User Available Function =================== + + function drip(IStakingRewards stakingContract) external returns (uint256); + + // ========================= Governor Functions ================================ + + function governorWithdrawRewardToken(uint256 amount, address governance) external; + + function governorRecover( + address tokenAddress, + address to, + uint256 amount, + IStakingRewards stakingContract + ) external; + + function setUpdateFrequency(uint256 _frequency, IStakingRewards stakingContract) external; + + function setIncentiveAmount(uint256 _incentiveAmount, IStakingRewards stakingContract) external; + + function setAmountToDistribute(uint256 _amountToDistribute, IStakingRewards stakingContract) external; + + function setDuration(uint256 _duration, IStakingRewards stakingContract) external; + + function setStakingContract( + address _stakingContract, + uint256 _duration, + uint256 _incentiveAmount, + uint256 _dripFrequency, + uint256 _amountToDistribute + ) external; + + function setNewRewardsDistributor(address newRewardsDistributor) external; + + function removeStakingContract(IStakingRewards stakingContract) external; +} diff --git a/contracts/interfaces/ISanToken.sol b/contracts/interfaces/ISanToken.sol new file mode 100644 index 0000000..2b85817 --- /dev/null +++ b/contracts/interfaces/ISanToken.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; + +/// @title ISanToken +/// @author Angle Core Team +/// @notice Interface for Angle's `SanToken` contract that handles sanTokens, tokens that are given to SLPs +/// contributing to a collateral for a given stablecoin +interface ISanToken is IERC20Upgradeable { + // ================================== StableMaster ============================= + + function mint(address account, uint256 amount) external; + + function burnFrom( + uint256 amount, + address burner, + address sender + ) external; + + function burnSelf(uint256 amount, address burner) external; + + function stableMaster() external view returns (address); + + function poolManager() external view returns (address); +} diff --git a/contracts/interfaces/IStableMaster.sol b/contracts/interfaces/IStableMaster.sol new file mode 100644 index 0000000..10616dc --- /dev/null +++ b/contracts/interfaces/IStableMaster.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +// Normally just importing `IPoolManager` should be sufficient, but for clarity here +// we prefer to import all concerned interfaces +import "./IPoolManager.sol"; +import "./IOracle.sol"; +import "./IPerpetualManager.sol"; +import "./ISanToken.sol"; + +// Struct to handle all the parameters to manage the fees +// related to a given collateral pool (associated to the stablecoin) +struct MintBurnData { + // Values of the thresholds to compute the minting fees + // depending on HA hedge (scaled by `BASE_PARAMS`) + uint64[] xFeeMint; + // Values of the fees at thresholds (scaled by `BASE_PARAMS`) + uint64[] yFeeMint; + // Values of the thresholds to compute the burning fees + // depending on HA hedge (scaled by `BASE_PARAMS`) + uint64[] xFeeBurn; + // Values of the fees at thresholds (scaled by `BASE_PARAMS`) + uint64[] yFeeBurn; + // Max proportion of collateral from users that can be covered by HAs + // It is exactly the same as the parameter of the same name in `PerpetualManager`, whenever one is updated + // the other changes accordingly + uint64 targetHAHedge; + // Minting fees correction set by the `FeeManager` contract: they are going to be multiplied + // to the value of the fees computed using the hedge curve + // Scaled by `BASE_PARAMS` + uint64 bonusMalusMint; + // Burning fees correction set by the `FeeManager` contract: they are going to be multiplied + // to the value of the fees computed using the hedge curve + // Scaled by `BASE_PARAMS` + uint64 bonusMalusBurn; + // Parameter used to limit the number of stablecoins that can be issued using the concerned collateral + uint256 capOnStableMinted; +} + +// Struct to handle all the variables and parameters to handle SLPs in the protocol +// including the fraction of interests they receive or the fees to be distributed to +// them +struct SLPData { + // Last timestamp at which the `sanRate` has been updated for SLPs + uint256 lastBlockUpdated; + // Fees accumulated from previous blocks and to be distributed to SLPs + uint256 lockedInterests; + // Max interests used to update the `sanRate` in a single block + // Should be in collateral token base + uint256 maxInterestsDistributed; + // Amount of fees left aside for SLPs and that will be distributed + // when the protocol is collateralized back again + uint256 feesAside; + // Part of the fees normally going to SLPs that is left aside + // before the protocol is collateralized back again (depends on collateral ratio) + // Updated by keepers and scaled by `BASE_PARAMS` + uint64 slippageFee; + // Portion of the fees from users minting and burning + // that goes to SLPs (the rest goes to surplus) + uint64 feesForSLPs; + // Slippage factor that's applied to SLPs exiting (depends on collateral ratio) + // If `slippage = BASE_PARAMS`, SLPs can get nothing, if `slippage = 0` they get their full claim + // Updated by keepers and scaled by `BASE_PARAMS` + uint64 slippage; + // Portion of the interests from lending + // that goes to SLPs (the rest goes to surplus) + uint64 interestsForSLPs; +} + +/// @title IStableMasterFunctions +/// @author Angle Core Team +/// @notice Interface for the `StableMaster` contract +interface IStableMasterFunctions { + function deploy( + address[] memory _governorList, + address _guardian, + address _agToken + ) external; + + // ============================== Lending ====================================== + + function accumulateInterest(uint256 gain) external; + + function signalLoss(uint256 loss) external; + + // ============================== HAs ========================================== + + function getStocksUsers() external view returns (uint256 maxCAmountInStable); + + function convertToSLP(uint256 amount, address user) external; + + // ============================== Keepers ====================================== + + function getCollateralRatio() external returns (uint256); + + function setFeeKeeper( + uint64 feeMint, + uint64 feeBurn, + uint64 _slippage, + uint64 _slippageFee + ) external; + + // ============================== AgToken ====================================== + + function updateStocksUsers(uint256 amount, address poolManager) external; + + // ============================= Governance ==================================== + + function setCore(address newCore) external; + + function addGovernor(address _governor) external; + + function removeGovernor(address _governor) external; + + function setGuardian(address newGuardian, address oldGuardian) external; + + function revokeGuardian(address oldGuardian) external; + + function setCapOnStableAndMaxInterests( + uint256 _capOnStableMinted, + uint256 _maxInterestsDistributed, + IPoolManager poolManager + ) external; + + function setIncentivesForSLPs( + uint64 _feesForSLPs, + uint64 _interestsForSLPs, + IPoolManager poolManager + ) external; + + function setUserFees( + IPoolManager poolManager, + uint64[] memory _xFee, + uint64[] memory _yFee, + uint8 _mint + ) external; + + function setTargetHAHedge(uint64 _targetHAHedge) external; + + function pause(bytes32 agent, IPoolManager poolManager) external; + + function unpause(bytes32 agent, IPoolManager poolManager) external; +} + +/// @title IStableMaster +/// @author Angle Core Team +/// @notice Previous interface with additionnal getters for public variables and mappings +interface IStableMaster is IStableMasterFunctions { + function agToken() external view returns (address); + + function collateralMap(IPoolManager poolManager) + external + view + returns ( + IERC20 token, + ISanToken sanToken, + IPerpetualManager perpetualManager, + IOracle oracle, + uint256 stocksUsers, + uint256 sanRate, + uint256 collatBase, + SLPData memory slpData, + MintBurnData memory feeData + ); +} diff --git a/contracts/interfaces/IStakingRewards.sol b/contracts/interfaces/IStakingRewards.sol new file mode 100644 index 0000000..135097f --- /dev/null +++ b/contracts/interfaces/IStakingRewards.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/// @title IStakingRewardsFunctions +/// @author Angle Core Team +/// @notice Interface for the staking rewards contract that interact with the `RewardsDistributor` contract +interface IStakingRewardsFunctions { + function notifyRewardAmount(uint256 reward) external; + + function recoverERC20( + address tokenAddress, + address to, + uint256 tokenAmount + ) external; + + function setNewRewardsDistribution(address newRewardsDistribution) external; +} + +/// @title IStakingRewards +/// @author Angle Core Team +/// @notice Previous interface with additionnal getters for public variables +interface IStakingRewards is IStakingRewardsFunctions { + function rewardToken() external view returns (IERC20); +} diff --git a/contracts/interfaces/IStrategy.sol b/contracts/interfaces/IStrategy.sol new file mode 100644 index 0000000..782eaf3 --- /dev/null +++ b/contracts/interfaces/IStrategy.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./IAccessControl.sol"; + +/// @title IStrategy +/// @author Inspired by Yearn with slight changes from Angle Core Team +/// @notice Interface for yield farming strategies +interface IStrategy is IAccessControl { + function estimatedAPR() external view returns (uint256); + + function poolManager() external view returns (address); + + function want() external view returns (address); + + function isActive() external view returns (bool); + + function estimatedTotalAssets() external view returns (uint256); + + function harvestTrigger(uint256 callCost) external view returns (bool); + + function harvest() external; + + function withdraw(uint256 _amountNeeded) external returns (uint256 amountFreed, uint256 _loss); + + function setEmergencyExit() external; + + function addGuardian(address _guardian) external; + + function revokeGuardian(address _guardian) external; +} diff --git a/contracts/interfaces/ITimelock.sol b/contracts/interfaces/ITimelock.sol new file mode 100644 index 0000000..8beb43f --- /dev/null +++ b/contracts/interfaces/ITimelock.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0 + +// Forked from https://github.com/compound-finance/compound-protocol/tree/master/contracts/Governance + +pragma solidity ^0.8.7; + +interface ITimelock { + function delay() external view returns (uint256); + + // solhint-disable-next-line func-name-mixedcase + function GRACE_PERIOD() external view returns (uint256); + + function acceptAdmin() external; + + function queuedTransactions(bytes32 hash) external view returns (bool); + + function queueTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external returns (bytes32); + + function cancelTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external; + + function executeTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external payable returns (bytes memory); +} + +interface ANGLEInterface { + function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96); +} diff --git a/contracts/interfaces/IWETH.sol b/contracts/interfaces/IWETH.sol new file mode 100644 index 0000000..1ca3256 --- /dev/null +++ b/contracts/interfaces/IWETH.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.5.0; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IWETH is IERC20 { + function deposit() external payable; + + function decimals() external view returns (uint256); + + function withdraw(uint256) external; +} diff --git a/contracts/interfaces/external/aave/DataTypes.sol b/contracts/interfaces/external/aave/DataTypes.sol new file mode 100644 index 0000000..9d094b1 --- /dev/null +++ b/contracts/interfaces/external/aave/DataTypes.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +library DataTypes { + // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. + struct ReserveData { + //stores the reserve configuration + ReserveConfigurationMap configuration; + //the liquidity index. Expressed in ray + uint128 liquidityIndex; + //variable borrow index. Expressed in ray + uint128 variableBorrowIndex; + //the current supply rate. Expressed in ray + uint128 currentLiquidityRate; + //the current variable borrow rate. Expressed in ray + uint128 currentVariableBorrowRate; + //the current stable borrow rate. Expressed in ray + uint128 currentStableBorrowRate; + uint40 lastUpdateTimestamp; + //tokens addresses + address aTokenAddress; + address stableDebtTokenAddress; + address variableDebtTokenAddress; + //address of the interest rate strategy + address interestRateStrategyAddress; + //the id of the reserve. Represents the position in the list of the active reserves + uint8 id; + } + + struct ReserveConfigurationMap { + //bit 0-15: LTV + //bit 16-31: Liq. threshold + //bit 32-47: Liq. bonus + //bit 48-55: Decimals + //bit 56: Reserve is active + //bit 57: reserve is frozen + //bit 58: borrowing is enabled + //bit 59: stable rate borrowing enabled + //bit 60-63: reserved + //bit 64-79: reserve factor + uint256 data; + } +} diff --git a/contracts/interfaces/external/aave/IAave.sol b/contracts/interfaces/external/aave/IAave.sol new file mode 100644 index 0000000..3476753 --- /dev/null +++ b/contracts/interfaces/external/aave/IAave.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import { DataTypes } from "./DataTypes.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IAaveIncentivesController { + function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256); + + function claimRewards( + address[] calldata assets, + uint256 amount, + address to + ) external returns (uint256); + + function getDistributionEnd() external view returns (uint256); + + function getAssetData(address asset) + external + view + returns ( + uint256, + uint256, + uint256 + ); +} + +interface IAToken is IERC20 { + function getIncentivesController() external view returns (IAaveIncentivesController); +} + +interface ILendingPool { + function deposit( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); +} + +interface ILendingPoolAddressesProvider { + function getLendingPool() external view returns (address); +} + +interface IProtocolDataProvider { + function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider); + + function getReserveConfigurationData(address asset) + external + view + returns ( + uint256 decimals, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus, + uint256 reserveFactor, + bool usageAsCollateralEnabled, + bool borrowingEnabled, + bool stableBorrowRateEnabled, + bool isActive, + bool isFrozen + ); + + function getReserveData(address asset) + external + view + returns ( + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 liquidityRate, + uint256 variableBorrowRate, + uint256 stableBorrowRate, + uint256 averageStableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex, + uint40 lastUpdateTimestamp + ); +} + +interface IReserveInterestRateStrategy { + function calculateInterestRates( + address reserve, + uint256 utilizationRate, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 averageStableBorrowRate, + uint256 reserveFactor + ) + external + view + returns ( + uint256 liquidityRate, + uint256 stableBorrowRate, + uint256 variableBorrowRate + ); +} + +interface IStakedAave { + function stake(address to, uint256 amount) external; + + function redeem(address to, uint256 amount) external; + + function cooldown() external; + + function claimRewards(address to, uint256 amount) external; + + function getTotalRewardsBalance(address) external view returns (uint256); + + function COOLDOWN_SECONDS() external view returns (uint256); + + function stakersCooldowns(address) external view returns (uint256); + + function UNSTAKE_WINDOW() external view returns (uint256); +} diff --git a/contracts/interfaces/external/compound/CErc20I.sol b/contracts/interfaces/external/compound/CErc20I.sol new file mode 100755 index 0000000..03f24ba --- /dev/null +++ b/contracts/interfaces/external/compound/CErc20I.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.5.0; + +import "./CTokenI.sol"; + +interface CErc20I is CTokenI { + function mint(uint256 mintAmount) external returns (uint256); + + function redeemUnderlying(uint256 redeemAmount) external returns (uint256); + + function underlying() external view returns (address); + + function borrow(uint256 borrowAmount) external returns (uint256); +} diff --git a/contracts/interfaces/external/compound/CEtherI.sol b/contracts/interfaces/external/compound/CEtherI.sol new file mode 100644 index 0000000..f85cdcb --- /dev/null +++ b/contracts/interfaces/external/compound/CEtherI.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.5.0; + +import "./CTokenI.sol"; + +interface CEtherI is CTokenI { + function mint() external payable; + + function redeemUnderlying(uint256 redeemAmount) external returns (uint256); + + function borrow(uint256 borrowAmount) external returns (uint256); +} diff --git a/contracts/interfaces/external/compound/CTokenI.sol b/contracts/interfaces/external/compound/CTokenI.sol new file mode 100644 index 0000000..54d1941 --- /dev/null +++ b/contracts/interfaces/external/compound/CTokenI.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; +import "./InterestRateModel.sol"; + +interface CTokenI { + function balanceOf(address owner) external view returns (uint256); + + function balanceOfUnderlying(address owner) external returns (uint256); + + function supplyRatePerBlock() external view returns (uint256); + + function exchangeRateCurrent() external returns (uint256); + + function exchangeRateStored() external view returns (uint256); + + function interestRateModel() external view returns (InterestRateModel); + + function totalReserves() external view returns (uint256); + + function reserveFactorMantissa() external view returns (uint256); + + function totalBorrows() external view returns (uint256); + + function totalSupply() external view returns (uint256); +} diff --git a/contracts/interfaces/external/compound/IComptroller.sol b/contracts/interfaces/external/compound/IComptroller.sol new file mode 100644 index 0000000..1a7e2bb --- /dev/null +++ b/contracts/interfaces/external/compound/IComptroller.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./CTokenI.sol"; + +interface IComptroller { + function compSupplySpeeds(address cToken) external view returns (uint256); + + function claimComp( + address[] memory holders, + CTokenI[] memory cTokens, + bool borrowers, + bool suppliers + ) external; +} diff --git a/contracts/interfaces/external/compound/InterestRateModel.sol b/contracts/interfaces/external/compound/InterestRateModel.sol new file mode 100755 index 0000000..42acca1 --- /dev/null +++ b/contracts/interfaces/external/compound/InterestRateModel.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +interface InterestRateModel { + /** + * @notice Calculates the current supply interest rate per block + * @param cash The total amount of cash the market has + * @param borrows The total amount of borrows the market has outstanding + * @param reserves The total amount of reserves the market has + * @param reserveFactorMantissa The current reserve factor the market has + * @return The supply rate per block (as a percentage, and scaled by 1e18) + */ + function getSupplyRate( + uint256 cash, + uint256 borrows, + uint256 reserves, + uint256 reserveFactorMantissa + ) external view returns (uint256); + + // Rinkeby function + function getBorrowRate( + uint256 cash, + uint256 borrows, + uint256 _reserves + ) external view returns (uint256, uint256); +} diff --git a/contracts/interfaces/external/curve/Curve.sol b/contracts/interfaces/external/curve/Curve.sol new file mode 100644 index 0000000..3b267d5 --- /dev/null +++ b/contracts/interfaces/external/curve/Curve.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.7; + +interface ICurveFi { + function get_virtual_price() external view returns (uint256); + + function add_liquidity( + // sBTC pool + uint256[3] calldata amounts, + uint256 min_mint_amount + ) external; + + function add_liquidity( + // bUSD pool + uint256[4] calldata amounts, + uint256 min_mint_amount + ) external; + + function add_liquidity( + // stETH pool + uint256[2] calldata amounts, + uint256 min_mint_amount + ) external payable; + + function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external; + + function remove_liquidity(uint256 _amount, uint256[4] calldata amounts) external; + + function remove_liquidity_one_coin( + uint256 _token_amount, + int128 i, + uint256 min_amount + ) external; + + function exchange( + int128 from, + int128 to, + uint256 _from_amount, + uint256 _min_to_amount + ) external payable; + + function balances(int128) external view returns (uint256); + + function get_dy( + int128 from, + int128 to, + uint256 _from_amount + ) external view returns (uint256); + + function calc_token_amount(uint256[2] calldata amounts, bool is_deposit) external view returns (uint256); +} + +interface Zap { + function remove_liquidity_one_coin( + uint256, + int128, + uint256 + ) external; +} diff --git a/contracts/interfaces/external/lido/ISteth.sol b/contracts/interfaces/external/lido/ISteth.sol new file mode 100644 index 0000000..caf5f14 --- /dev/null +++ b/contracts/interfaces/external/lido/ISteth.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface ISteth is IERC20 { + event Submitted(address sender, uint256 amount, address referral); + + function submit(address) external payable returns (uint256); +} diff --git a/contracts/interfaces/external/uniswap/IUniswapRouter.sol b/contracts/interfaces/external/uniswap/IUniswapRouter.sol new file mode 100644 index 0000000..c692147 --- /dev/null +++ b/contracts/interfaces/external/uniswap/IUniswapRouter.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +struct ExactInputParams { + bytes path; + address recipient; + uint256 deadline; + uint256 amountIn; + uint256 amountOutMinimum; +} + +/// @title Router token swapping functionality +/// @notice Functions for swapping tokens via Uniswap V3 +interface IUniswapV3Router { + /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path + /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata + /// @return amountOut The amount of the received token + function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); +} + +/// @title Router for price estimation functionality +/// @notice Functions for getting the price of one token with respect to another using Uniswap V2 +/// @dev This interface is only used for non critical elements of the protocol +interface IUniswapV2Router { + /// @notice Given an input asset amount, returns the maximum output amount of the + /// other asset (accounting for fees) given reserves. + /// @param path Addresses of the pools used to get prices + function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); + + function swapExactTokensForTokens( + uint256 swapAmount, + uint256 minExpected, + address[] calldata path, + address receiver, + uint256 swapDeadline + ) external; +} diff --git a/contracts/interfaces/mock/IERC20MINT.sol b/contracts/interfaces/mock/IERC20MINT.sol new file mode 100644 index 0000000..fb40b06 --- /dev/null +++ b/contracts/interfaces/mock/IERC20MINT.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +interface IERC20MINT is IERC20 { + function mint(address account, uint256 amount) external; +} diff --git a/contracts/interfaces/mock/IMockUniswapV3Pool.sol b/contracts/interfaces/mock/IMockUniswapV3Pool.sol new file mode 100644 index 0000000..8af916c --- /dev/null +++ b/contracts/interfaces/mock/IMockUniswapV3Pool.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title Router token swapping functionality +/// @notice Functions for swapping tokens via Uniswap V3 +interface IMockUniswapV3Pool { + /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp + /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing + /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, + /// you must call it with secondsAgos = [3600, 0]. + /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in + /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. + /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned + /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp + /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block + /// timestamp + function observe(uint32[] calldata secondsAgos) + external + view + returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s); + + /// @notice Increase the maximum number of price and liquidity observations that this pool will store + /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to + /// the input observationCardinalityNext. + /// @param observationCardinalityNext The desired minimum number of observations for the pool to store + function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external; +} diff --git a/contracts/mock/MockCurveStETHETH.sol b/contracts/mock/MockCurveStETHETH.sol new file mode 100644 index 0000000..5643d0a --- /dev/null +++ b/contracts/mock/MockCurveStETHETH.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +// Contract we have to fix flash attacks +contract MockCurveStETHETH { + using SafeERC20 for IERC20; + + address public stETH; + uint256 public dy; + + constructor(address _stETH) { + stETH = _stETH; + dy = 10**18; + } + + receive() external payable {} + + function exchange( + int128 from, + int128 to, + uint256 _from_amount, + uint256 _min_to_amount + ) external payable { + if (from == 0 && to == 1) { + IERC20(stETH).transfer(msg.sender, (msg.value * dy) / 10**18); + } else { + IERC20(stETH).transferFrom(msg.sender, address(this), _from_amount); + (bool sent, ) = msg.sender.call{ value: (_from_amount * 10**18) / dy }(""); + require(sent, "Failed to send Ether"); + } + } + + function setDy(uint256 _dy) external { + dy = _dy; + } + + function get_dy( + int128 from, + int128 to, + uint256 _from_amount + ) external view returns (uint256) { + return (_from_amount * dy) / 10**18; + } +} diff --git a/contracts/mock/MockStETH.sol b/contracts/mock/MockStETH.sol new file mode 100644 index 0000000..6db6d7b --- /dev/null +++ b/contracts/mock/MockStETH.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./MockToken.sol"; + +contract MockStETH is MockToken { + event Deposit(address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + + /// @notice stablecoin constructor + /// @param name_ the stablecoin name (example 'agEUR') + /// @param symbol_ the stablecoin symbol ('agEUR') + /// @dev To account for the fact that the balance increases we can simply mint stETH to the concerned address + constructor( + string memory name_, + string memory symbol_, + uint8 decimal_ + ) MockToken(name_, symbol_, decimal_) {} + + receive() external payable {} + + function submit(address) external payable returns (uint256) { + _mint(msg.sender, msg.value); + return msg.value; + } +} diff --git a/contracts/mock/MockStrategy.sol b/contracts/mock/MockStrategy.sol new file mode 100644 index 0000000..2124772 --- /dev/null +++ b/contracts/mock/MockStrategy.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../interfaces/IPoolManager.sol"; + +contract MockStrategy { + address public poolManager; + + address public want; + + constructor(address _poolManager, address _want) { + poolManager = _poolManager; + want = _want; + } + + function report( + uint256 gain, + uint256 loss, + uint256 debtPayment + ) external { + IPoolManager(poolManager).report(gain, loss, debtPayment); + } + + function withdraw(uint256 amount) external pure returns (uint256, uint256) { + return (amount, 1); + } + + function creditAvailable() external view returns (uint256 credit) { + credit = IPoolManager(poolManager).creditAvailable(); + } +} diff --git a/contracts/mock/MockToken.sol b/contracts/mock/MockToken.sol new file mode 100644 index 0000000..f3f4707 --- /dev/null +++ b/contracts/mock/MockToken.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockToken is ERC20 { + event Minting(address indexed _to, address indexed _minter, uint256 _amount); + + event Burning(address indexed _from, address indexed _burner, uint256 _amount); + + uint8 internal _decimal; + + /// @notice stablecoin constructor + /// @param name_ the stablecoin name (example 'agEUR') + /// @param symbol_ the stablecoin symbol ('agEUR') + constructor( + string memory name_, + string memory symbol_, + uint8 decimal_ + ) ERC20(name_, symbol_) { + _decimal = decimal_; + } + + /// @dev Returns the number of decimals used to get its user representation. + /// For example, if `decimals` equals `2`, a balance of `505` tokens should + /// be displayed to a user as `5,05` (`505 / 10 ** 2`). + function decimals() public view override returns (uint8) { + return _decimal; + } + + /// @notice allow to mint + /// @param account the account to mint to + /// @param amount the amount to mint + function mint(address account, uint256 amount) external { + _mint(account, amount); + emit Minting(account, msg.sender, amount); + } + + /// @notice allow to burn + /// @param account the account to burn from + /// @param amount the amount of agToken to burn from caller + function burn(address account, uint256 amount) public { + _burn(account, amount); + emit Burning(account, msg.sender, amount); + } + + function setAllowance(address from, address to) public { + _approve(from, to, type(uint256).max); + } +} diff --git a/contracts/poolManager/PoolManager.sol b/contracts/poolManager/PoolManager.sol new file mode 100644 index 0000000..b4af4fd --- /dev/null +++ b/contracts/poolManager/PoolManager.sol @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./PoolManagerInternal.sol"; + +/// @title PoolManager +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This file contains the functions that are callable by governance or by other contracts of the protocol +/// @dev References to this contract are called `PoolManager` +contract PoolManager is PoolManagerInternal, IPoolManagerFunctions { + using SafeERC20 for IERC20; + + // ============================ Constructor ==================================== + + /// @notice Constructor of the `PoolManager` contract + /// @param _token Address of the collateral + /// @param _stableMaster Reference to the master stablecoin (`StableMaster`) interface + function initialize(address _token, IStableMaster _stableMaster) + external + initializer + zeroCheck(_token) + zeroCheck(address(_stableMaster)) + { + __AccessControl_init(); + + // Creating the correct references + stableMaster = _stableMaster; + token = IERC20(_token); + + // Access Control + // The roles in this contract can only be modified from the `StableMaster` + // For the moment `StableMaster` never uses the `GOVERNOR_ROLE` + _setupRole(STABLEMASTER_ROLE, address(stableMaster)); + _setRoleAdmin(STABLEMASTER_ROLE, STABLEMASTER_ROLE); + _setRoleAdmin(GOVERNOR_ROLE, STABLEMASTER_ROLE); + _setRoleAdmin(GUARDIAN_ROLE, STABLEMASTER_ROLE); + // No admin is set for `STRATEGY_ROLE`, checks are made in the appropriate functions + // `addStrategy` and `revokeStrategy` + } + + /* + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() initializer {} + */ + + // ========================= `StableMaster` Functions ========================== + + /// @notice Changes the references to contracts from this protocol with which this collateral `PoolManager` interacts + /// and propagates some references to the `perpetualManager` and `feeManager` contracts + /// @param governorList List of the governor addresses of protocol + /// @param guardian Address of the guardian of the protocol (it can be revoked) + /// @param _perpetualManager New reference to the `PerpetualManager` contract containing all the logic for HAs + /// @param _feeManager Reference to the `FeeManager` contract that will serve for the `PerpetualManager` contract + /// @param _oracle Reference to the `Oracle` contract that will serve for the `PerpetualManager` contract + function deployCollateral( + address[] memory governorList, + address guardian, + IPerpetualManager _perpetualManager, + IFeeManager _feeManager, + IOracle _oracle + ) external override onlyRole(STABLEMASTER_ROLE) { + // These references need to be stored to be able to propagate changes and maintain + // the protocol's integrity when changes are posted from the `StableMaster` + perpetualManager = _perpetualManager; + feeManager = _feeManager; + + // Access control + for (uint256 i = 0; i < governorList.length; i++) { + _grantRole(GOVERNOR_ROLE, governorList[i]); + _grantRole(GUARDIAN_ROLE, governorList[i]); + } + _grantRole(GUARDIAN_ROLE, guardian); + + // Propagates the changes to the other involved contracts + perpetualManager.deployCollateral(governorList, guardian, _feeManager, _oracle); + _feeManager.deployCollateral(governorList, guardian, address(_perpetualManager)); + + // `StableMaster` and `PerpetualManager` need to have approval to directly transfer some of + // this contract's tokens + token.safeIncreaseAllowance(address(stableMaster), type(uint256).max); + token.safeIncreaseAllowance(address(_perpetualManager), type(uint256).max); + } + + /// @notice Adds a new governor address and echoes it to other contracts + /// @param _governor New governor address + function addGovernor(address _governor) external override onlyRole(STABLEMASTER_ROLE) { + // Access control for this contract + _grantRole(GOVERNOR_ROLE, _governor); + // Echoes the change to other contracts interacting with this collateral `PoolManager` + // Since the other contracts interacting with this `PoolManager` do not have governor roles, + // we just need it to set the new governor as guardian in these contracts + _addGuardian(_governor); + } + + /// @notice Removes a governor address and echoes it to other contracts + /// @param _governor Governor address to remove + function removeGovernor(address _governor) external override onlyRole(STABLEMASTER_ROLE) { + // Access control for this contract + _revokeRole(GOVERNOR_ROLE, _governor); + _revokeGuardian(_governor); + } + + /// @notice Changes the guardian address and echoes it to other contracts that interact with this `PoolManager` + /// @param _guardian New guardian address + /// @param guardian Old guardian address to revoke + function setGuardian(address _guardian, address guardian) external override onlyRole(STABLEMASTER_ROLE) { + _revokeGuardian(guardian); + _addGuardian(_guardian); + } + + /// @notice Revokes the guardian address and echoes the change to other contracts that interact with this `PoolManager` + /// @param guardian Address of the guardian to revoke + function revokeGuardian(address guardian) external override onlyRole(STABLEMASTER_ROLE) { + _revokeGuardian(guardian); + } + + /// @notice Allows to propagate the change of keeper for the collateral/stablecoin pair + /// @param _feeManager New `FeeManager` contract + function setFeeManager(IFeeManager _feeManager) external override onlyRole(STABLEMASTER_ROLE) { + // Changing the reference in the `PerpetualManager` contract where keepers are involved + feeManager = _feeManager; + perpetualManager.setFeeManager(_feeManager); + } + + // ============================= Yield Farming ================================= + + /// @notice Provides an estimated Annual Percentage Rate for SLPs based on lending to other protocols + /// @dev This function is an estimation and is made for external use only + /// @dev This does not take into account transaction fees which accrue to SLPs too + /// @dev This can be manipulated by a flash loan attack (SLP deposit/ withdraw) via `_getTotalAsset` + /// when entering you should make sure this hasn't be called by a flash loan and look + /// at a mean of past APR. + function estimatedAPR() external view returns (uint256 apr) { + apr = 0; + (, ISanToken sanTokenForAPR, , , , uint256 sanRate, , SLPData memory slpData, ) = stableMaster.collateralMap( + IPoolManager(address(this)) + ); + uint256 supply = sanTokenForAPR.totalSupply(); + + // `sanRate` should never be equal to 0 + if (supply == 0) return type(uint256).max; + + for (uint256 i = 0; i < strategyList.length; i++) { + apr = + apr + + (strategies[strategyList[i]].debtRatio * IStrategy(strategyList[i]).estimatedAPR()) / + BASE_PARAMS; + } + apr = (apr * slpData.interestsForSLPs * _getTotalAsset()) / sanRate / supply; + } + + /// @notice Tells a strategy how much it can borrow from this `PoolManager` + /// @return Amount of token a strategy has access to as a credit line + /// @dev Since this function is a view function, there is no need to have an access control logic + /// even though it will just be relevant for a strategy + /// @dev Manipulating `_getTotalAsset` with a flashloan will only + /// result in tokens being transferred at the cost of the caller + function creditAvailable() external view override returns (uint256) { + StrategyParams storage params = strategies[msg.sender]; + + uint256 target = (_getTotalAsset() * params.debtRatio) / BASE_PARAMS; + + if (target < params.totalStrategyDebt) return 0; + + return Math.min(target - params.totalStrategyDebt, _getBalance()); + } + + /// @notice Tells a strategy how much it owes to this `PoolManager` + /// @return Amount of token a strategy has to reimburse + /// @dev Manipulating `_getTotalAsset` with a flashloan will only + /// result in tokens being transferred at the cost of the caller + function debtOutstanding() external view override returns (uint256) { + StrategyParams storage params = strategies[msg.sender]; + + uint256 target = (_getTotalAsset() * params.debtRatio) / BASE_PARAMS; + + if (target > params.totalStrategyDebt) return 0; + + return (params.totalStrategyDebt - target); + } + + /// @notice Reports the gains or loss made by a strategy + /// @param gain Amount strategy has realized as a gain on its investment since its + /// last report, and is free to be given back to `PoolManager` as earnings + /// @param loss Amount strategy has realized as a loss on its investment since its + /// last report, and should be accounted for on the `PoolManager`'s balance sheet. + /// The loss will reduce the `debtRatio`. The next time the strategy will harvest, + /// it will pay back the debt in an attempt to adjust to the new debt limit. + /// @param debtPayment Amount strategy has made available to cover outstanding debt + /// @dev This is the main contact point where the strategy interacts with the `PoolManager` + /// @dev The strategy reports back what it has free, then the `PoolManager` contract "decides" + /// whether to take some back or give it more. Note that the most it can + /// take is `gain + _debtPayment`, and the most it can give is all of the + /// remaining reserves. Anything outside of those bounds is abnormal behavior. + function report( + uint256 gain, + uint256 loss, + uint256 debtPayment + ) external override onlyRole(STRATEGY_ROLE) { + require(token.balanceOf(msg.sender) >= gain + debtPayment, "72"); + + StrategyParams storage params = strategies[msg.sender]; + // Updating parameters in the `perpetualManager` + // This needs to be done now because it has implications in `_getTotalAsset()` + params.totalStrategyDebt = params.totalStrategyDebt + gain - loss; + totalDebt = totalDebt + gain - loss; + params.lastReport = block.timestamp; + + // Warning: `_getTotalAsset` could be manipulated by flashloan attacks. + // It may allow external users to transfer funds into strategy or remove funds + // from the strategy. Yet, as it does not impact the profit or loss and as attackers + // have no interest in making such txs to have a direct profit, we let it as is. + // The only issue is if the strategy is compromised; in this case governance + // should revoke the strategy + uint256 target = ((_getTotalAsset()) * params.debtRatio) / BASE_PARAMS; + if (target > params.totalStrategyDebt) { + // If the strategy has some credit left, tokens can be transferred to this strategy + uint256 available = Math.min(target - params.totalStrategyDebt, _getBalance()); + params.totalStrategyDebt = params.totalStrategyDebt + available; + totalDebt = totalDebt + available; + if (available > 0) { + token.safeTransfer(msg.sender, available); + } + } else { + uint256 available = Math.min(params.totalStrategyDebt - target, debtPayment + gain); + params.totalStrategyDebt = params.totalStrategyDebt - available; + totalDebt = totalDebt - available; + if (available > 0) { + token.safeTransferFrom(msg.sender, address(this), available); + } + } + emit StrategyReported(msg.sender, gain, loss, debtPayment, params.totalStrategyDebt); + + // Handle gains before losses + if (gain > 0) { + uint256 gainForSurplus = (gain * interestsForSurplus) / BASE_PARAMS; + uint256 adminDebtPre = adminDebt; + // Depending on the current admin debt distribute the necessary gain from the strategies + if (adminDebtPre == 0) interestsAccumulated += gainForSurplus; + else if (adminDebtPre <= gainForSurplus) { + interestsAccumulated += gainForSurplus - adminDebtPre; + adminDebt = 0; + } else adminDebt -= gainForSurplus; + stableMaster.accumulateInterest(gain - gainForSurplus); + emit FeesDistributed(gain); + } + + // Handle eventual losses + if (loss > 0) { + uint256 lossForSurplus = (loss * interestsForSurplus) / BASE_PARAMS; + uint256 interestsAccumulatedPreLoss = interestsAccumulated; + // If the loss can not be entirely soaked by the interests to be distributed then + // the protocol keeps track of the debt + if (lossForSurplus > interestsAccumulatedPreLoss) { + interestsAccumulated = 0; + adminDebt += lossForSurplus - interestsAccumulatedPreLoss; + } else interestsAccumulated -= lossForSurplus; + // The rest is incurred to SLPs + stableMaster.signalLoss(loss - lossForSurplus); + } + } + + // =========================== Governor Functions ============================== + + /// @notice Allows to recover any ERC20 token, including the token handled by this contract, and to send it + /// to a contract + /// @param tokenAddress Address of the token to recover + /// @param to Address of the contract to send collateral to + /// @param amountToRecover Amount of collateral to transfer + /// @dev As this function can be used to transfer funds to another contract, it has to be a `GOVERNOR` function + /// @dev In case the concerned token is the specific token handled by this contract, this function checks that the + /// amount entered is not too big and approximates the surplus of the protocol + /// @dev To esimate the amount of user claims on the concerned collateral, this function uses the `stocksUsers` for + /// this collateral, but this is just an approximation as users can claim the collateral of their choice provided + /// that they own a stablecoin + /// @dev The sanity check excludes the HA claims: to get a sense of it, this function would need to compute the cash out + /// amount of all the perpetuals, and this cannot be done on-chain in a cheap manner + /// @dev Overall, even though there is a sanity check, this function relies on the fact that governance is not corrupted + /// in this protocol and will not try to withdraw too much funds + function recoverERC20( + address tokenAddress, + address to, + uint256 amountToRecover + ) external onlyRole(GOVERNOR_ROLE) { + if (tokenAddress == address(token)) { + // Fetching info from the `StableMaster` + ( + , + ISanToken sanToken, + , + IOracle oracle, + uint256 stocksUsers, + uint256 sanRate, + uint256 collatBase, + , + + ) = IStableMaster(stableMaster).collateralMap(IPoolManager(address(this))); + + // Checking if there are enough reserves for the amount to withdraw + require( + _getTotalAsset() >= + amountToRecover + + (sanToken.totalSupply() * sanRate) / + BASE_TOKENS + + (stocksUsers * collatBase) / + oracle.readUpper() + + interestsAccumulated, + "66" + ); + + token.safeTransfer(to, amountToRecover); + } else { + IERC20(tokenAddress).safeTransfer(to, amountToRecover); + } + emit Recovered(tokenAddress, to, amountToRecover); + } + + /// @notice Adds a strategy to the `PoolManager` + /// @param strategy The address of the strategy to add + /// @param _debtRatio The share of the total assets that the strategy has access to + /// @dev Multiple checks are made. For instance, the contract must not already belong to the `PoolManager` + /// and the underlying token of the strategy has to be consistent with the `PoolManager` contracts + /// @dev This function is a `governor` function and not a `guardian` one because a `guardian` could add a strategy + /// enabling the withdraw of the funds of the protocol + /// @dev The `_debtRatio` should be expressed in `BASE_PARAMS` + function addStrategy(address strategy, uint256 _debtRatio) external onlyRole(GOVERNOR_ROLE) zeroCheck(strategy) { + StrategyParams storage params = strategies[strategy]; + + require(params.lastReport == 0, "73"); + require(address(this) == IStrategy(strategy).poolManager(), "74"); + // Using current code, this condition should always be verified as in the constructor + // of the strategy the `want()` is set to the token of this `PoolManager` + require(address(token) == IStrategy(strategy).want(), "75"); + require(debtRatio + _debtRatio <= BASE_PARAMS, "76"); + + // Add strategy to approved strategies + params.lastReport = 1; + params.totalStrategyDebt = 0; + params.debtRatio = _debtRatio; + + _grantRole(STRATEGY_ROLE, strategy); + + // Update global parameters + debtRatio += _debtRatio; + emit StrategyAdded(strategy, debtRatio); + + strategyList.push(strategy); + } + + // =========================== Guardian Functions ============================== + + /// @notice Sets a new surplus distributor to which surplus from the protocol will be pushed + /// @param newSurplusConverter Address to which the role needs to be granted + /// @dev It is as if the `GUARDIAN_ROLE` was admin of the `SURPLUS_DISTRIBUTOR_ROLE` + /// @dev The address can be the zero address in case the protocol revokes the `surplusConverter` + function setSurplusConverter(address newSurplusConverter) external onlyRole(GUARDIAN_ROLE) { + address oldSurplusConverter = surplusConverter; + surplusConverter = newSurplusConverter; + emit SurplusConverterUpdated(newSurplusConverter, oldSurplusConverter); + } + + /// @notice Sets the share of the interests going directly to the surplus + /// @param _interestsForSurplus New value of the interests going directly to the surplus for buybacks + /// @dev Guardian should make sure the incentives for SLPs are still high enough for them to enter the protocol + function setInterestsForSurplus(uint64 _interestsForSurplus) + external + onlyRole(GUARDIAN_ROLE) + onlyCompatibleFees(_interestsForSurplus) + { + interestsForSurplus = _interestsForSurplus; + emit InterestsForSurplusUpdated(_interestsForSurplus); + } + + /// @notice Modifies the funds a strategy has access to + /// @param strategy The address of the Strategy + /// @param _debtRatio The share of the total assets that the strategy has access to + /// @dev The update has to be such that the `debtRatio` does not exceeds the 100% threshold + /// as this `PoolManager` cannot lend collateral that it doesn't not own. + /// @dev `_debtRatio` is stored as a uint256 but as any parameter of the protocol, it should be expressed + /// in `BASE_PARAMS` + function updateStrategyDebtRatio(address strategy, uint256 _debtRatio) external onlyRole(GUARDIAN_ROLE) { + _updateStrategyDebtRatio(strategy, _debtRatio); + } + + /// @notice Triggers an emergency exit for a strategy and then harvests it to fetch all the funds + /// @param strategy The address of the `Strategy` + function setStrategyEmergencyExit(address strategy) external onlyRole(GUARDIAN_ROLE) { + _updateStrategyDebtRatio(strategy, 0); + IStrategy(strategy).setEmergencyExit(); + IStrategy(strategy).harvest(); + } + + /// @notice Revokes a strategy + /// @param strategy The address of the strategy to revoke + /// @dev This should only be called after the following happened in order: the `strategy.debtRatio` has been set to 0, + /// `harvest` has been called enough times to recover all capital gain/losses. + function revokeStrategy(address strategy) external onlyRole(GUARDIAN_ROLE) { + StrategyParams storage params = strategies[strategy]; + + require(params.debtRatio == 0, "77"); + require(params.totalStrategyDebt == 0, "77"); + uint256 strategyListLength = strategyList.length; + require(params.lastReport != 0 && strategyListLength >= 1, "78"); + // It has already been checked whether the strategy was a valid strategy + for (uint256 i = 0; i < strategyListLength - 1; i++) { + if (strategyList[i] == strategy) { + strategyList[i] = strategyList[strategyListLength - 1]; + break; + } + } + + strategyList.pop(); + + // Update global parameters + debtRatio -= params.debtRatio; + delete strategies[strategy]; + + _revokeRole(STRATEGY_ROLE, strategy); + + emit StrategyRevoked(strategy); + } + + /// @notice Withdraws a given amount from a strategy + /// @param strategy The address of the strategy + /// @param amount The amount to withdraw + /// @dev This function tries to recover `amount` from the strategy, but it may not go through + /// as we may not be able to withdraw from the lending protocol the full amount + /// @dev In this last case we only update the parameters by setting the loss as the gap between + /// what has been asked and what has been returned. + function withdrawFromStrategy(IStrategy strategy, uint256 amount) external onlyRole(GUARDIAN_ROLE) { + StrategyParams storage params = strategies[address(strategy)]; + require(params.lastReport != 0, "78"); + + uint256 loss; + (amount, loss) = strategy.withdraw(amount); + + // Handling eventual losses + params.totalStrategyDebt = params.totalStrategyDebt - loss - amount; + totalDebt = totalDebt - loss - amount; + + emit StrategyReported(address(strategy), 0, loss, amount - loss, params.totalStrategyDebt); + + // Handle eventual losses + // With the strategy we are using in current tests, it is going to be impossible to have + // a positive loss by calling strategy.withdraw, this function indeed calls _liquidatePosition + // which output value is always zero + if (loss > 0) stableMaster.signalLoss(loss); + } + + // =================== Surplus Distributor Function ============================ + + /// @notice Allows to push interests revenue accumulated by the protocol to the `surplusConverter` to do buybacks + /// or another form of redistribution to ANGLE or veANGLE token holders + /// @dev This function is permissionless and anyone can transfer the `interestsAccumulated` by the protocol + /// to the `surplusConverter` + function pushSurplus() external { + // If the `surplusConverter` has not been initialized, surplus should not be distributed + // Storing the `surplusConverter` in an intermediate variable to avoid multiple reads in + // storage + address surplusConverterMem = surplusConverter; + require(surplusConverterMem != address(0), "0"); + uint256 amount = interestsAccumulated; + interestsAccumulated = 0; + // Storing the `token` in memory to avoid duplicate reads in storage + IERC20 tokenMem = token; + tokenMem.safeTransfer(surplusConverterMem, amount); + emit Recovered(address(tokenMem), surplusConverterMem, amount); + } + + // ======================== Getters - View Functions =========================== + + /// @notice Gets the current balance of this `PoolManager` contract + /// @return The amount of the underlying collateral that the contract currently owns + /// @dev This balance does not take into account what has been lent to strategies + function getBalance() external view override returns (uint256) { + return _getBalance(); + } + + /// @notice Gets the total amount of collateral that is controlled by this `PoolManager` contract + /// @return The amount of collateral owned by this contract plus the amount that has been lent to strategies + /// @dev This is the value that is used to compute the debt ratio for a given strategy + function getTotalAsset() external view override returns (uint256) { + return _getTotalAsset(); + } +} diff --git a/contracts/poolManager/PoolManagerEvents.sol b/contracts/poolManager/PoolManagerEvents.sol new file mode 100644 index 0000000..6b25db0 --- /dev/null +++ b/contracts/poolManager/PoolManagerEvents.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; + +import "../external/AccessControlUpgradeable.sol"; + +import "../interfaces/IFeeManager.sol"; +import "../interfaces/IPoolManager.sol"; +import "../interfaces/ISanToken.sol"; +import "../interfaces/IPerpetualManager.sol"; +import "../interfaces/IStableMaster.sol"; +import "../interfaces/IStrategy.sol"; + +import "../utils/FunctionUtils.sol"; + +/// @title PoolManagerEvents +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This contract contains all the events of the `PoolManager` Contract +contract PoolManagerEvents { + event FeesDistributed(uint256 amountDistributed); + + event Recovered(address indexed token, address indexed to, uint256 amount); + + event StrategyAdded(address indexed strategy, uint256 debtRatio); + + event InterestsForSurplusUpdated(uint64 _interestsForSurplus); + + event SurplusConverterUpdated(address indexed newSurplusConverter, address indexed oldSurplusConverter); + + event StrategyRevoked(address indexed strategy); + + event StrategyReported( + address indexed strategy, + uint256 gain, + uint256 loss, + uint256 debtPayment, + uint256 totalDebt + ); +} diff --git a/contracts/poolManager/PoolManagerInternal.sol b/contracts/poolManager/PoolManagerInternal.sol new file mode 100644 index 0000000..df05e21 --- /dev/null +++ b/contracts/poolManager/PoolManagerInternal.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./PoolManagerStorageV3.sol"; + +/// @title PoolManagerInternal +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This file contains all the internal functions of the `PoolManager` contract +contract PoolManagerInternal is PoolManagerStorageV3 { + using SafeERC20 for IERC20; + + // Roles need to be defined here because there are some internal access control functions + // in the `PoolManagerInternal` file + + /// @notice Role for `StableMaster` only + bytes32 public constant STABLEMASTER_ROLE = keccak256("STABLEMASTER_ROLE"); + /// @notice Role for governors only + bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE"); + /// @notice Role for guardians and governors + bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); + /// @notice Role for `Strategy` only + bytes32 public constant STRATEGY_ROLE = keccak256("STRATEGY_ROLE"); + + // ======================= Access Control and Governance ======================= + + /// @notice Adds a new guardian address and echoes the change to the contracts + /// that interact with this collateral `PoolManager` + /// @param _guardian New guardian address + function _addGuardian(address _guardian) internal { + // Granting the new role + // Access control for this contract + _grantRole(GUARDIAN_ROLE, _guardian); + // Propagating the new role in other contract + perpetualManager.grantRole(GUARDIAN_ROLE, _guardian); + feeManager.grantRole(GUARDIAN_ROLE, _guardian); + uint256 strategyListLength = strategyList.length; + for (uint256 i = 0; i < strategyListLength; i++) { + IStrategy(strategyList[i]).addGuardian(_guardian); + } + } + + /// @notice Revokes the guardian role and propagates the change to other contracts + /// @param guardian Old guardian address to revoke + function _revokeGuardian(address guardian) internal { + _revokeRole(GUARDIAN_ROLE, guardian); + perpetualManager.revokeRole(GUARDIAN_ROLE, guardian); + feeManager.revokeRole(GUARDIAN_ROLE, guardian); + uint256 strategyListLength = strategyList.length; + for (uint256 i = 0; i < strategyListLength; i++) { + IStrategy(strategyList[i]).revokeGuardian(guardian); + } + } + + // ============================= Yield Farming ================================= + + /// @notice Internal version of `updateStrategyDebtRatio` + /// @dev Updates the debt ratio for a strategy + function _updateStrategyDebtRatio(address strategy, uint256 _debtRatio) internal { + StrategyParams storage params = strategies[strategy]; + require(params.lastReport != 0, "78"); + debtRatio = debtRatio + _debtRatio - params.debtRatio; + require(debtRatio <= BASE_PARAMS, "76"); + params.debtRatio = _debtRatio; + emit StrategyAdded(strategy, debtRatio); + } + + // ============================ Utils ========================================== + + /// @notice Returns this `PoolManager`'s reserve of collateral (not including what has been lent) + function _getBalance() internal view returns (uint256) { + return token.balanceOf(address(this)); + } + + /// @notice Returns the amount of assets owned by this `PoolManager` + /// @dev This sums the current balance of the contract to what has been given to strategies + /// @dev This amount can be manipulated by flash loans + function _getTotalAsset() internal view returns (uint256) { + return _getBalance() + totalDebt; + } +} diff --git a/contracts/poolManager/PoolManagerStorageV1.sol b/contracts/poolManager/PoolManagerStorageV1.sol new file mode 100644 index 0000000..7d2dd83 --- /dev/null +++ b/contracts/poolManager/PoolManagerStorageV1.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./PoolManagerEvents.sol"; + +/// @title PoolManagerStorageV1 +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This file contains most of the variables and parameters stored for this contract. It does not contain all +/// as the storage file has been split into multiple files to avoid clashes when upgrading the smart contract +contract PoolManagerStorageV1 is PoolManagerEvents, FunctionUtils { + // ================ References to contracts that cannot be modified ============ + + /// @notice Interface for the underlying token accepted by this contract + IERC20 public token; + + /// @notice Reference to the `PerpetualManager` for this collateral/stablecoin pair + /// `PerpetualManager` is an upgradeable contract, there is therefore no need to be able to update this reference + IPerpetualManager public perpetualManager; + + /// @notice Reference to the `StableMaster` contract corresponding to this `PoolManager` + IStableMaster public stableMaster; + + // ============== References to contracts that can be modified ================= + + /// @notice FeeManager contract for this collateral/stablecoin pair + /// This reference can be updated by the `StableMaster` and change is going to be propagated + /// to the `PerpetualManager` from this contract + IFeeManager public feeManager; + + // ============================= Yield Farming ================================= + + /// @notice Funds currently given to strategies + uint256 public totalDebt; + + /// @notice Proportion of the funds managed dedicated to strategies + /// Has to be between 0 and `BASE_PARAMS` + uint256 public debtRatio; + + /// The struct `StrategyParams` is defined in the interface `IPoolManager` + /// @notice Mapping between the address of a strategy contract and its corresponding details + mapping(address => StrategyParams) public strategies; + + /// @notice List of the current strategies + address[] public strategyList; +} diff --git a/contracts/poolManager/PoolManagerStorageV2.sol b/contracts/poolManager/PoolManagerStorageV2.sol new file mode 100644 index 0000000..5b66c1c --- /dev/null +++ b/contracts/poolManager/PoolManagerStorageV2.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./PoolManagerStorageV1.sol"; + +/// @title PoolManagerStorageV2 +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This file imports the `AccessControlUpgradeable` +contract PoolManagerStorageV2 is PoolManagerStorageV1, AccessControlUpgradeable { + +} diff --git a/contracts/poolManager/PoolManagerStorageV3.sol b/contracts/poolManager/PoolManagerStorageV3.sol new file mode 100644 index 0000000..51e5207 --- /dev/null +++ b/contracts/poolManager/PoolManagerStorageV3.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./PoolManagerStorageV2.sol"; + +/// @title PoolManagerStorageV3 +/// @author Angle Core Team +/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin, +/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol +/// to get yield on its collateral +/// @dev This file contains the last variables and parameters stored for this contract. The reason for not storing them +/// directly in `PoolManagerStorageV1` is that theywere introduced after a first deployment and may have introduced a +/// storage clash when upgrading +contract PoolManagerStorageV3 is PoolManagerStorageV2 { + /// @notice Address of the surplus distributor allowed to distribute rewards + address public surplusConverter; + + /// @notice Share of the interests going to surplus and share going to SLPs + uint64 public interestsForSurplus; + + /// @notice Interests accumulated by the protocol and to be distributed through ANGLE or veANGLE + /// token holders + uint256 public interestsAccumulated; + + /// @notice Debt that must be paid by admins after a loss on a strategy + uint256 public adminDebt; +} diff --git a/contracts/stableMaster/StableMaster.sol b/contracts/stableMaster/StableMaster.sol new file mode 100644 index 0000000..2b345b5 --- /dev/null +++ b/contracts/stableMaster/StableMaster.sol @@ -0,0 +1,567 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./StableMasterInternal.sol"; + +/// @title StableMaster +/// @author Angle Core Team +/// @notice `StableMaster` is the contract handling all the collateral types accepted for a given stablecoin +/// It does all the accounting and is the point of entry in the protocol for stable holders and seekers as well as SLPs +/// @dev This file contains the core functions of the `StableMaster` contract +contract StableMaster is StableMasterInternal, IStableMasterFunctions, AccessControlUpgradeable { + using SafeERC20 for IERC20; + + /// @notice Role for governors only + bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE"); + /// @notice Role for guardians and governors + bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); + /// @notice Role for `Core` only, used to propagate guardian and governors + bytes32 public constant CORE_ROLE = keccak256("CORE_ROLE"); + + bytes32 public constant STABLE = keccak256("STABLE"); + bytes32 public constant SLP = keccak256("SLP"); + + // ============================ DEPLOYER ======================================= + + /// @notice Creates the access control logic for the governor and guardian addresses + /// @param governorList List of the governor addresses of the protocol + /// @param guardian Guardian address of the protocol + /// @param _agToken Reference to the `AgToken`, that is the ERC20 token handled by the `StableMaster` + /// @dev This function is called by the `Core` when a stablecoin is deployed to maintain consistency + /// across the governor and guardian roles + /// @dev When this function is called by the `Core`, it has already been checked that the `stableMaster` + /// corresponding to the `agToken` was this `stableMaster` + function deploy( + address[] memory governorList, + address guardian, + address _agToken + ) external override onlyRole(CORE_ROLE) { + for (uint256 i = 0; i < governorList.length; i++) { + _grantRole(GOVERNOR_ROLE, governorList[i]); + _grantRole(GUARDIAN_ROLE, governorList[i]); + } + _grantRole(GUARDIAN_ROLE, guardian); + agToken = IAgToken(_agToken); + // Since there is only one address that can be the `AgToken`, and since `AgToken` + // is not to be admin of any role, we do not define any access control role for it + } + + // ============================ STRATEGIES ===================================== + + /// @notice Takes into account the gains made while lending and distributes it to SLPs by updating the `sanRate` + /// @param gain Interests accumulated from lending + /// @dev This function is called by a `PoolManager` contract having some yield farming strategies associated + /// @dev To prevent flash loans, the `sanRate` is not directly updated, it is updated at the blocks that follow + function accumulateInterest(uint256 gain) external override { + // Searching collateral data + Collateral storage col = collateralMap[IPoolManager(msg.sender)]; + _contractMapCheck(col); + // A part of the gain goes to SLPs, the rest to the surplus of the protocol + _updateSanRate((gain * col.slpData.interestsForSLPs) / BASE_PARAMS, col); + } + + /// @notice Takes into account a loss made by a yield farming strategy + /// @param loss Loss made by the yield farming strategy + /// @dev This function is called by a `PoolManager` contract having some yield farming strategies associated + /// @dev Fees are not accumulated for this function before being distributed: everything is directly used to + /// update the `sanRate` + function signalLoss(uint256 loss) external override { + // Searching collateral data + IPoolManager poolManager = IPoolManager(msg.sender); + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + uint256 sanMint = col.sanToken.totalSupply(); + if (sanMint != 0) { + // Updating the `sanRate` and the `lockedInterests` by taking into account a loss + if (col.sanRate * sanMint + col.slpData.lockedInterests * BASE_TOKENS > loss * BASE_TOKENS) { + // The loss is first taken from the `lockedInterests` + uint256 withdrawFromLoss = col.slpData.lockedInterests; + + if (withdrawFromLoss >= loss) { + withdrawFromLoss = loss; + } + + col.slpData.lockedInterests -= withdrawFromLoss; + col.sanRate -= ((loss - withdrawFromLoss) * BASE_TOKENS) / sanMint; + } else { + // Normally it should be set to 0, but this would imply that no SLP can enter afterwards + // we therefore set it to 1 (equivalent to 10**(-18)) + col.sanRate = 1; + col.slpData.lockedInterests = 0; + // As it is a critical time, governance pauses SLPs to solve the situation + _pause(keccak256(abi.encodePacked(SLP, address(poolManager)))); + } + emit SanRateUpdated(address(col.token), col.sanRate); + } + } + + // ============================== HAs ========================================== + + /// @notice Transforms a HA position into a SLP Position + /// @param amount The amount to transform + /// @param user Address to mint sanTokens to + /// @dev Can only be called by a `PerpetualManager` contract + /// @dev This is typically useful when a HA wishes to cash out but there is not enough collateral + /// in reserves + function convertToSLP(uint256 amount, address user) external override { + // Data about the `PerpetualManager` calling the function is fetched using the `contractMap` + IPoolManager poolManager = _contractMap[msg.sender]; + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + // If SLPs are paused, in this situation, then this transaction should revert + // In this extremely rare case, governance should take action and also pause HAs + _whenNotPaused(SLP, address(poolManager)); + _updateSanRate(0, col); + col.sanToken.mint(user, (amount * BASE_TOKENS) / col.sanRate); + } + + /// @notice Sets the proportion of `stocksUsers` available for perpetuals + /// @param _targetHAHedge New value of the hedge ratio that the protocol wants to arrive to + /// @dev Can only be called by the `PerpetualManager` + function setTargetHAHedge(uint64 _targetHAHedge) external override { + // Data about the `PerpetualManager` calling the function is fetched using the `contractMap` + IPoolManager poolManager = _contractMap[msg.sender]; + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + col.feeData.targetHAHedge = _targetHAHedge; + // No need to issue an event here, one has already been issued by the corresponding `PerpetualManager` + } + + // ============================ VIEW FUNCTIONS ================================= + + /// @notice Transmits to the `PerpetualManager` the max amount of collateral (in stablecoin value) HAs can hedge + /// @return _stocksUsers All stablecoins currently assigned to the pool of the caller + /// @dev This function will not return something relevant if it is not called by a `PerpetualManager` + function getStocksUsers() external view override returns (uint256 _stocksUsers) { + _stocksUsers = collateralMap[_contractMap[msg.sender]].stocksUsers; + } + + /// @notice Returns the collateral ratio for this stablecoin + /// @dev The ratio returned is scaled by `BASE_PARAMS` since the value is used to + /// in the `FeeManager` contrat to be compared with the values in `xArrays` expressed in `BASE_PARAMS` + function getCollateralRatio() external view override returns (uint256) { + uint256 mints = agToken.totalSupply(); + if (mints == 0) { + // If nothing has been minted, the collateral ratio is infinity + return type(uint256).max; + } + uint256 val; + for (uint256 i = 0; i < _managerList.length; i++) { + // Oracle needs to be called for each collateral to compute the collateral ratio + val += collateralMap[_managerList[i]].oracle.readQuote(_managerList[i].getTotalAsset()); + } + return (val * BASE_PARAMS) / mints; + } + + // ============================== KEEPERS ====================================== + + /// @notice Updates all the fees not depending on personal agents inputs via a keeper calling the corresponding + /// function in the `FeeManager` contract + /// @param _bonusMalusMint New corrector of user mint fees for this collateral. These fees will correct + /// the mint fees from users that just depend on the hedge curve by HAs by introducing other dependencies. + /// In normal times they will be equal to `BASE_PARAMS` meaning fees will just depend on the hedge ratio + /// @param _bonusMalusBurn New corrector of user burn fees, depending on collateral ratio + /// @param _slippage New global slippage (the SLP fees from withdrawing) factor + /// @param _slippageFee New global slippage fee (the non distributed accumulated fees) factor + function setFeeKeeper( + uint64 _bonusMalusMint, + uint64 _bonusMalusBurn, + uint64 _slippage, + uint64 _slippageFee + ) external override { + // Fetching data about the `FeeManager` contract calling this function + // It is stored in the `_contractMap` + Collateral storage col = collateralMap[_contractMap[msg.sender]]; + _contractMapCheck(col); + + col.feeData.bonusMalusMint = _bonusMalusMint; + col.feeData.bonusMalusBurn = _bonusMalusBurn; + col.slpData.slippage = _slippage; + col.slpData.slippageFee = _slippageFee; + // An event is already emitted in the `FeeManager` contract + } + + // ============================== AgToken ====================================== + + /// @notice Allows the `agToken` contract to update the `stocksUsers` for a given collateral after a burn + /// with no redeem + /// @param amount Amount by which `stocksUsers` should decrease + /// @param poolManager Reference to `PoolManager` for which `stocksUsers` needs to be updated + /// @dev This function can be called by the `agToken` contract after a burn of agTokens for which no collateral has been + /// redeemed + function updateStocksUsers(uint256 amount, address poolManager) external override { + require(msg.sender == address(agToken), "3"); + Collateral storage col = collateralMap[IPoolManager(poolManager)]; + _contractMapCheck(col); + require(col.stocksUsers >= amount, "4"); + col.stocksUsers -= amount; + emit StocksUsersUpdated(address(col.token), col.stocksUsers); + } + + // ================================= GOVERNANCE ================================ + + // =============================== Core Functions ============================== + + /// @notice Changes the `Core` contract + /// @param newCore New core address + /// @dev This function can only be called by the `Core` contract + function setCore(address newCore) external override onlyRole(CORE_ROLE) { + // Access control for this contract + _revokeRole(CORE_ROLE, address(_core)); + _grantRole(CORE_ROLE, newCore); + _core = ICore(newCore); + } + + /// @notice Adds a new governor address + /// @param governor New governor address + /// @dev This function propagates changes from `Core` to other contracts + /// @dev Propagating changes like that allows to maintain the protocol's integrity + function addGovernor(address governor) external override onlyRole(CORE_ROLE) { + // Access control for this contract + _grantRole(GOVERNOR_ROLE, governor); + _grantRole(GUARDIAN_ROLE, governor); + + for (uint256 i = 0; i < _managerList.length; i++) { + // The `PoolManager` will echo the changes across all the corresponding contracts + _managerList[i].addGovernor(governor); + } + } + + /// @notice Removes a governor address which loses its role + /// @param governor Governor address to remove + /// @dev This function propagates changes from `Core` to other contracts + /// @dev Propagating changes like that allows to maintain the protocol's integrity + /// @dev It has already been checked in the `Core` that this address could be removed + /// and that it would not put the protocol in a situation with no governor at all + function removeGovernor(address governor) external override onlyRole(CORE_ROLE) { + // Access control for this contract + _revokeRole(GOVERNOR_ROLE, governor); + _revokeRole(GUARDIAN_ROLE, governor); + + for (uint256 i = 0; i < _managerList.length; i++) { + // The `PoolManager` will echo the changes across all the corresponding contracts + _managerList[i].removeGovernor(governor); + } + } + + /// @notice Changes the guardian address + /// @param newGuardian New guardian address + /// @param oldGuardian Old guardian address + /// @dev This function propagates changes from `Core` to other contracts + /// @dev The zero check for the guardian address has already been performed by the `Core` + /// contract + function setGuardian(address newGuardian, address oldGuardian) external override onlyRole(CORE_ROLE) { + _revokeRole(GUARDIAN_ROLE, oldGuardian); + _grantRole(GUARDIAN_ROLE, newGuardian); + + for (uint256 i = 0; i < _managerList.length; i++) { + _managerList[i].setGuardian(newGuardian, oldGuardian); + } + } + + /// @notice Revokes the guardian address + /// @param oldGuardian Guardian address to revoke + /// @dev This function propagates changes from `Core` to other contracts + function revokeGuardian(address oldGuardian) external override onlyRole(CORE_ROLE) { + _revokeRole(GUARDIAN_ROLE, oldGuardian); + for (uint256 i = 0; i < _managerList.length; i++) { + _managerList[i].revokeGuardian(oldGuardian); + } + } + + // ============================= Governor Functions ============================ + + /// @notice Deploys a new collateral by creating the correct references in the corresponding contracts + /// @param poolManager Contract managing and storing this collateral for this stablecoin + /// @param perpetualManager Contract managing HA perpetuals for this stablecoin + /// @param oracle Reference to the oracle that will give the price of the collateral with respect to the stablecoin + /// @param sanToken Reference to the sanTokens associated to the collateral + /// @dev All the references in parameters should correspond to contracts that have already been deployed and + /// initialized with appropriate references + /// @dev After calling this function, governance should initialize all parameters corresponding to this new collateral + function deployCollateral( + IPoolManager poolManager, + IPerpetualManager perpetualManager, + IFeeManager feeManager, + IOracle oracle, + ISanToken sanToken + ) external onlyRole(GOVERNOR_ROLE) { + // If the `sanToken`, `poolManager`, `perpetualManager` and `feeManager` were zero + // addresses, the following require would fail + // The only elements that are checked here are those that are defined in the constructors/initializers + // of the concerned contracts + require( + sanToken.stableMaster() == address(this) && + sanToken.poolManager() == address(poolManager) && + poolManager.stableMaster() == address(this) && + perpetualManager.poolManager() == address(poolManager) && + // If the `feeManager` is not initialized with the correct `poolManager` then this function + // will revert when `poolManager.deployCollateral` will be executed + feeManager.stableMaster() == address(this), + "9" + ); + // Checking if the base of the tokens and of the oracle are not similar with one another + address token = poolManager.token(); + uint256 collatBase = 10**(IERC20Metadata(token).decimals()); + // If the address of the oracle was the zero address, the following would revert + require(oracle.inBase() == collatBase, "11"); + // Checking if the collateral has not already been deployed + Collateral storage col = collateralMap[poolManager]; + require(address(col.token) == address(0), "13"); + + // Creating the correct references + col.token = IERC20(token); + col.sanToken = sanToken; + col.perpetualManager = perpetualManager; + col.oracle = oracle; + // Initializing with the correct values + col.sanRate = BASE_TOKENS; + col.collatBase = collatBase; + + // Adding the correct references in the `contractMap` we use in order not to have to pass addresses when + // calling the `StableMaster` from the `PerpetualManager` contract, or the `FeeManager` contract + // This is equivalent to granting Access Control roles for these contracts + _contractMap[address(perpetualManager)] = poolManager; + _contractMap[address(feeManager)] = poolManager; + _managerList.push(poolManager); + + // Pausing agents at deployment to leave governance time to set parameters + // The `PerpetualManager` contract is automatically paused after being initialized, so HAs will not be able to + // interact with the protocol + _pause(keccak256(abi.encodePacked(SLP, address(poolManager)))); + _pause(keccak256(abi.encodePacked(STABLE, address(poolManager)))); + + // Fetching the governor list and the guardian to initialize the `poolManager` correctly + address[] memory governorList = _core.governorList(); + address guardian = _core.guardian(); + + // Propagating the deployment and passing references to the corresponding contracts + poolManager.deployCollateral(governorList, guardian, perpetualManager, feeManager, oracle); + emit CollateralDeployed(address(poolManager), address(perpetualManager), address(sanToken), address(oracle)); + } + + /// @notice Removes a collateral from the list of accepted collateral types and pauses all actions associated + /// to this collateral + /// @param poolManager Reference to the contract managing this collateral for this stablecoin in the protocol + /// @param settlementContract Settlement contract that will be used to close everyone's positions and to let + /// users, SLPs and HAs redeem if not all a portion of their claim + /// @dev Since this function has the ability to transfer the contract's funds to another contract, it should + /// only be accessible to the governor + /// @dev Before calling this function, governance should make sure that all the collateral lent to strategies + /// has been withdrawn + function revokeCollateral(IPoolManager poolManager, ICollateralSettler settlementContract) + external + onlyRole(GOVERNOR_ROLE) + { + // Checking if the `poolManager` given here is well in the list of managers and taking advantage of that to remove + // the `poolManager` from the list + uint256 indexMet; + uint256 managerListLength = _managerList.length; + require(managerListLength >= 1, "10"); + for (uint256 i = 0; i < managerListLength - 1; i++) { + if (_managerList[i] == poolManager) { + indexMet = 1; + _managerList[i] = _managerList[managerListLength - 1]; + break; + } + } + require(indexMet == 1 || _managerList[managerListLength - 1] == poolManager, "10"); + _managerList.pop(); + Collateral memory col = collateralMap[poolManager]; + + // Deleting the references of the associated contracts: `perpetualManager` and `keeper` in the + // `_contractMap` and `poolManager` from the `collateralMap` + delete _contractMap[poolManager.feeManager()]; + delete _contractMap[address(col.perpetualManager)]; + delete collateralMap[poolManager]; + emit CollateralRevoked(address(poolManager)); + + // Pausing entry (and exits for HAs) + col.perpetualManager.pause(); + // No need to pause `SLP` and `STABLE_HOLDERS` as deleting the entry associated to the `poolManager` + // in the `collateralMap` will make everything revert + + // Transferring the whole balance to global settlement + uint256 balance = col.token.balanceOf(address(poolManager)); + col.token.safeTransferFrom(address(poolManager), address(settlementContract), balance); + + // Settlement works with a fixed oracle value for HAs, it needs to be computed here + uint256 oracleValue = col.oracle.readLower(); + // Notifying the global settlement contract with the properties of the contract to settle + // In case of global shutdown, there would be one settlement contract per collateral type + // Not using the `lockedInterests` to update the value of the sanRate + settlementContract.triggerSettlement(oracleValue, col.sanRate, col.stocksUsers); + } + + // ============================= Guardian Functions ============================ + + /// @notice Pauses an agent's actions within this contract for a given collateral type for this stablecoin + /// @param agent Bytes representing the agent (`SLP` or `STABLE`) and the collateral type that is going to + /// be paused. To get the `bytes32` from a string, we use in Solidity a `keccak256` function + /// @param poolManager Reference to the contract managing this collateral for this stablecoin in the protocol and + /// for which `agent` needs to be paused + /// @dev If agent is `STABLE`, it is going to be impossible for users to mint stablecoins using collateral or to burn + /// their stablecoins + /// @dev If agent is `SLP`, it is going to be impossible for SLPs to deposit collateral and receive + /// sanTokens in exchange, or to withdraw collateral from their sanTokens + function pause(bytes32 agent, IPoolManager poolManager) external override onlyRole(GUARDIAN_ROLE) { + Collateral storage col = collateralMap[poolManager]; + // Checking for the `poolManager` + _contractMapCheck(col); + _pause(keccak256(abi.encodePacked(agent, address(poolManager)))); + } + + /// @notice Unpauses an agent's action for a given collateral type for this stablecoin + /// @param agent Agent (`SLP` or `STABLE`) to unpause the action of + /// @param poolManager Reference to the associated `PoolManager` + /// @dev Before calling this function, the agent should have been paused for this collateral + function unpause(bytes32 agent, IPoolManager poolManager) external override onlyRole(GUARDIAN_ROLE) { + Collateral storage col = collateralMap[poolManager]; + // Checking for the `poolManager` + _contractMapCheck(col); + _unpause(keccak256(abi.encodePacked(agent, address(poolManager)))); + } + + /// @notice Updates the `stocksUsers` for a given pair of collateral + /// @param amount Amount of `stocksUsers` to transfer from a pool to another + /// @param poolManagerUp Reference to `PoolManager` for which `stocksUsers` needs to increase + /// @param poolManagerDown Reference to `PoolManager` for which `stocksUsers` needs to decrease + /// @dev This function can be called in case where the reserves of the protocol for each collateral do not exactly + /// match what is stored in the `stocksUsers` because of increases or decreases in collateral prices at times + /// in which the protocol was not fully hedged by HAs + /// @dev With this function, governance can allow/prevent more HAs coming in a pool while preventing/allowing HAs + /// from other pools because the accounting variable of `stocksUsers` does not really match + function rebalanceStocksUsers( + uint256 amount, + IPoolManager poolManagerUp, + IPoolManager poolManagerDown + ) external onlyRole(GUARDIAN_ROLE) { + Collateral storage colUp = collateralMap[poolManagerUp]; + Collateral storage colDown = collateralMap[poolManagerDown]; + // Checking for the `poolManager` + _contractMapCheck(colUp); + _contractMapCheck(colDown); + // The invariant `col.stocksUsers <= col.capOnStableMinted` should remain true even after a + // governance update + require(colUp.stocksUsers + amount <= colUp.feeData.capOnStableMinted, "8"); + colDown.stocksUsers -= amount; + colUp.stocksUsers += amount; + emit StocksUsersUpdated(address(colUp.token), colUp.stocksUsers); + emit StocksUsersUpdated(address(colDown.token), colDown.stocksUsers); + } + + /// @notice Propagates the change of oracle for one collateral to all the contracts which need to have + /// the correct oracle reference + /// @param _oracle New oracle contract for the pair collateral/stablecoin + /// @param poolManager Reference to the `PoolManager` contract associated to the collateral + function setOracle(IOracle _oracle, IPoolManager poolManager) + external + onlyRole(GOVERNOR_ROLE) + zeroCheck(address(_oracle)) + { + Collateral storage col = collateralMap[poolManager]; + // Checking for the `poolManager` + _contractMapCheck(col); + require(col.oracle != _oracle, "12"); + // The `inBase` of the new oracle should be the same as the `_collatBase` stored for this collateral + require(col.collatBase == _oracle.inBase(), "11"); + col.oracle = _oracle; + emit OracleUpdated(address(poolManager), address(_oracle)); + col.perpetualManager.setOracle(_oracle); + } + + /// @notice Changes the parameters to cap the number of stablecoins you can issue using one + /// collateral type and the maximum interests you can distribute to SLPs in a sanRate update + /// in a block + /// @param _capOnStableMinted New value of the cap + /// @param _maxInterestsDistributed Maximum amount of interests distributed to SLPs in a block + /// @param poolManager Reference to the `PoolManager` contract associated to the collateral + function setCapOnStableAndMaxInterests( + uint256 _capOnStableMinted, + uint256 _maxInterestsDistributed, + IPoolManager poolManager + ) external override onlyRole(GUARDIAN_ROLE) { + Collateral storage col = collateralMap[poolManager]; + // Checking for the `poolManager` + _contractMapCheck(col); + // The invariant `col.stocksUsers <= col.capOnStableMinted` should remain true even after a + // governance update + require(_capOnStableMinted >= col.stocksUsers, "8"); + col.feeData.capOnStableMinted = _capOnStableMinted; + col.slpData.maxInterestsDistributed = _maxInterestsDistributed; + emit CapOnStableAndMaxInterestsUpdated(address(poolManager), _capOnStableMinted, _maxInterestsDistributed); + } + + /// @notice Sets a new `FeeManager` contract and removes the old one which becomes useless + /// @param newFeeManager New `FeeManager` contract + /// @param oldFeeManager Old `FeeManager` contract + /// @param poolManager Reference to the contract managing this collateral for this stablecoin in the protocol + /// and associated to the `FeeManager` to update + function setFeeManager( + address newFeeManager, + address oldFeeManager, + IPoolManager poolManager + ) external onlyRole(GUARDIAN_ROLE) zeroCheck(newFeeManager) { + Collateral storage col = collateralMap[poolManager]; + // Checking for the `poolManager` + _contractMapCheck(col); + require(_contractMap[oldFeeManager] == poolManager, "10"); + require(newFeeManager != oldFeeManager, "14"); + delete _contractMap[oldFeeManager]; + _contractMap[newFeeManager] = poolManager; + emit FeeManagerUpdated(address(poolManager), newFeeManager); + poolManager.setFeeManager(IFeeManager(newFeeManager)); + } + + /// @notice Sets the proportion of fees from burn/mint of users and the proportion + /// of lending interests going to SLPs + /// @param _feesForSLPs New proportion of mint/burn fees going to SLPs + /// @param _interestsForSLPs New proportion of interests from lending going to SLPs + /// @dev The higher these proportions the bigger the APY for SLPs + /// @dev These proportions should be inferior to `BASE_PARAMS` + function setIncentivesForSLPs( + uint64 _feesForSLPs, + uint64 _interestsForSLPs, + IPoolManager poolManager + ) external override onlyRole(GUARDIAN_ROLE) onlyCompatibleFees(_feesForSLPs) onlyCompatibleFees(_interestsForSLPs) { + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + col.slpData.feesForSLPs = _feesForSLPs; + col.slpData.interestsForSLPs = _interestsForSLPs; + emit SLPsIncentivesUpdated(address(poolManager), _feesForSLPs, _interestsForSLPs); + } + + /// @notice Sets the x array (ie ratios between amount hedged by HAs and amount to hedge) + /// and the y array (ie values of fees at thresholds) used to compute mint and burn fees for users + /// @param poolManager Reference to the `PoolManager` handling the collateral + /// @param _xFee Thresholds of hedge ratios + /// @param _yFee Values of the fees at thresholds + /// @param _mint Whether mint fees or burn fees should be updated + /// @dev The evolution of the fees between two thresholds is linear + /// @dev The length of the two arrays should be the same + /// @dev The values of `_xFee` should be in ascending order + /// @dev For mint fees, values in the y-array below should normally be decreasing: the higher the `x` the cheaper + /// it should be for stable seekers to come in as a high `x` corresponds to a high demand for volatility and hence + /// to a situation where all the collateral can be hedged + /// @dev For burn fees, values in the array below should normally be decreasing: the lower the `x` the cheaper it should + /// be for stable seekers to go out, as a low `x` corresponds to low demand for volatility and hence + /// to a situation where the protocol has a hard time covering its collateral + function setUserFees( + IPoolManager poolManager, + uint64[] memory _xFee, + uint64[] memory _yFee, + uint8 _mint + ) external override onlyRole(GUARDIAN_ROLE) onlyCompatibleInputArrays(_xFee, _yFee) { + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + if (_mint > 0) { + col.feeData.xFeeMint = _xFee; + col.feeData.yFeeMint = _yFee; + } else { + col.feeData.xFeeBurn = _xFee; + col.feeData.yFeeBurn = _yFee; + } + emit FeeArrayUpdated(address(poolManager), _xFee, _yFee, _mint); + } +} diff --git a/contracts/stableMaster/StableMasterEvents.sol b/contracts/stableMaster/StableMasterEvents.sol new file mode 100644 index 0000000..c6e627d --- /dev/null +++ b/contracts/stableMaster/StableMasterEvents.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +import "../external/AccessControlUpgradeable.sol"; + +import "../interfaces/IAgToken.sol"; +import "../interfaces/ICollateralSettler.sol"; +import "../interfaces/ICore.sol"; +import "../interfaces/IFeeManager.sol"; +import "../interfaces/IOracle.sol"; +import "../interfaces/IPerpetualManager.sol"; +import "../interfaces/IPoolManager.sol"; +import "../interfaces/ISanToken.sol"; +import "../interfaces/IStableMaster.sol"; + +import "../utils/FunctionUtils.sol"; +import "../utils/PausableMapUpgradeable.sol"; + +/// @title StableMasterEvents +/// @author Angle Core Team +/// @notice `StableMaster` is the contract handling all the collateral types accepted for a given stablecoin +/// It does all the accounting and is the point of entry in the protocol for stable holders and seekers as well as SLPs +/// @dev This file contains all the events of the `StableMaster` contract +contract StableMasterEvents { + event SanRateUpdated(address indexed _token, uint256 _newSanRate); + + event StocksUsersUpdated(address indexed _poolManager, uint256 _stocksUsers); + + event MintedStablecoins(address indexed _poolManager, uint256 amount, uint256 amountForUserInStable); + + event BurntStablecoins(address indexed _poolManager, uint256 amount, uint256 redeemInC); + + // ============================= Governors ===================================== + + event CollateralDeployed( + address indexed _poolManager, + address indexed _perpetualManager, + address indexed _sanToken, + address _oracle + ); + + event CollateralRevoked(address indexed _poolManager); + + // ========================= Parameters update ================================= + + event OracleUpdated(address indexed _poolManager, address indexed _oracle); + + event FeeManagerUpdated(address indexed _poolManager, address indexed newFeeManager); + + event CapOnStableAndMaxInterestsUpdated( + address indexed _poolManager, + uint256 _capOnStableMinted, + uint256 _maxInterestsDistributed + ); + + event SLPsIncentivesUpdated(address indexed _poolManager, uint64 _feesForSLPs, uint64 _interestsForSLPs); + + event FeeArrayUpdated(address indexed _poolManager, uint64[] _xFee, uint64[] _yFee, uint8 _type); +} diff --git a/contracts/stableMaster/StableMasterFront.sol b/contracts/stableMaster/StableMasterFront.sol new file mode 100644 index 0000000..da0803a --- /dev/null +++ b/contracts/stableMaster/StableMasterFront.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./StableMaster.sol"; + +/// @title StableMasterFront +/// @author Angle Core Team +/// @notice `StableMaster` is the contract handling all the collateral types accepted for a given stablecoin +/// It does all the accounting and is the point of entry in the protocol for stable holders and seekers as well as SLPs +/// @dev This file contains the front end, that is all external functions associated to the given stablecoin +contract StableMasterFront is StableMaster { + using SafeERC20 for IERC20; + + // ============================ CONSTRUCTORS AND DEPLOYERS ===================== + + /// @notice Initializes the `StableMaster` contract + /// @param core_ Address of the `Core` contract handling all the different `StableMaster` contracts + function initialize(address core_) external zeroCheck(core_) initializer { + __AccessControl_init(); + // Access control + _core = ICore(core_); + _setupRole(CORE_ROLE, core_); + // `Core` is admin of all roles + _setRoleAdmin(CORE_ROLE, CORE_ROLE); + _setRoleAdmin(GOVERNOR_ROLE, CORE_ROLE); + _setRoleAdmin(GUARDIAN_ROLE, CORE_ROLE); + // All the roles that are specific to a given collateral can be changed by the governor + // in the `deployCollateral`, `revokeCollateral` and `setFeeManager` functions by updating the `contractMap` + } + + /* + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() initializer {} + */ + + // ============================= USERS ========================================= + + /// @notice Lets a user send collateral to the system to mint stablecoins + /// @param amount Amount of collateral sent + /// @param user Address of the contract or the person to give the minted tokens to + /// @param poolManager Address of the `PoolManager` of the required collateral + /// @param minStableAmount Minimum amount of stablecoins the user wants to get with this transaction + /// @dev This function works as a swap from a user perspective from collateral to stablecoins + /// @dev It is impossible to mint tokens and to have them sent to the zero address: there + /// would be an issue with the `_mint` function called by the `AgToken` contract + /// @dev The parameter `minStableAmount` serves as a slippage protection for users + /// @dev From a user perspective, this function is equivalent to a swap between collateral and + /// stablecoins + function mint( + uint256 amount, + address user, + IPoolManager poolManager, + uint256 minStableAmount + ) external { + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + // Checking if the contract is paused for this agent + _whenNotPaused(STABLE, address(poolManager)); + + // No overflow check are needed for the amount since it's never casted to `int` and Solidity 0.8.0 + // automatically handles overflows + col.token.safeTransferFrom(msg.sender, address(poolManager), amount); + + // Getting a quote for the amount of stablecoins to issue + // We read the lowest oracle value we get for this collateral/stablecoin pair: it's the one + // that is most at the advantage of the protocol + // Decimals are handled directly in the oracle contract + uint256 amountForUserInStable = col.oracle.readQuoteLower(amount); + + // Getting the fees paid for this transaction, expressed in `BASE_PARAMS` + // Floor values are taken for fees computation, as what is earned by users is lost by SLP + // when calling `_updateSanRate` and vice versa + uint256 fees = _computeFeeMint(amountForUserInStable, col); + + // Computing the net amount that will be taken into account for this user by deducing fees + amountForUserInStable = (amountForUserInStable * (BASE_PARAMS - fees)) / BASE_PARAMS; + // Checking if the user got more stablecoins than the least amount specified in the parameters of the + // function + require(amountForUserInStable >= minStableAmount, "15"); + + // Updating the `stocksUsers` for this collateral, that is the amount of collateral that was + // brought by users + col.stocksUsers += amountForUserInStable; + // Checking if stablecoins can still be issued using this collateral type + require(col.stocksUsers <= col.feeData.capOnStableMinted, "16"); + + // Event needed to track `col.stocksUsers` off-chain + emit MintedStablecoins(address(poolManager), amount, amountForUserInStable); + + // Distributing the fees taken to SLPs + // The `fees` variable computed above is a proportion expressed in `BASE_PARAMS`. + // To compute the amount of fees in collateral value, we can directly use the `amount` of collateral + // entered by the user + // Not all the fees are distributed to SLPs, a portion determined by `col.slpData.feesForSLPs` goes to surplus + _updateSanRate((amount * fees * col.slpData.feesForSLPs) / (BASE_PARAMS**2), col); + + // Minting + agToken.mint(user, amountForUserInStable); + } + + /// @notice Lets a user burn agTokens (stablecoins) and receive the collateral specified by the `poolManager` + /// in exchange + /// @param amount Amount of stable asset burnt + /// @param burner Address from which the agTokens will be burnt + /// @param dest Address where collateral is going to be + /// @param poolManager Collateral type requested by the user burning + /// @param minCollatAmount Minimum amount of collateral that the user is willing to get for this transaction + /// @dev The `msg.sender` should have approval to burn from the `burner` or the `msg.sender` should be the `burner` + /// @dev If there are not enough reserves this transaction will revert and the user will have to come back to the + /// protocol with a correct amount. Checking for the reserves currently available in the `PoolManager` + /// is something that should be handled by the front interacting with this contract + /// @dev In case there are not enough reserves, strategies should be harvested or their debt ratios should be adjusted + /// by governance to make sure that users, HAs or SLPs withdrawing always have free collateral they can use + /// @dev From a user perspective, this function is equivalent to a swap from stablecoins to collateral + function burn( + uint256 amount, + address burner, + address dest, + IPoolManager poolManager, + uint256 minCollatAmount + ) external { + // Searching collateral data + Collateral storage col = collateralMap[poolManager]; + // Checking the collateral requested + _contractMapCheck(col); + _whenNotPaused(STABLE, address(poolManager)); + + // Checking if the amount is not going to make the `stocksUsers` negative + // A situation like that is likely to happen if users mint using one collateral type and in volume redeem + // another collateral type + // In this situation, governance should rapidly react to pause the pool and then rebalance the `stocksUsers` + // between different collateral types, or at least rebalance what is stored in the reserves through + // the `recoverERC20` function followed by a swap and then a transfer + require(amount <= col.stocksUsers, "17"); + + // Burning the tokens will revert if there are not enough tokens in balance or if the `msg.sender` + // does not have approval from the burner + // A reentrancy attack is potentially possible here as state variables are written after the burn, + // but as the `AgToken` is a protocol deployed contract, it can be trusted. Still, `AgToken` is + // upgradeable by governance, the following could become risky in case of a governance attack + if (burner == msg.sender) { + agToken.burnSelf(amount, burner); + } else { + agToken.burnFrom(amount, burner, msg.sender); + } + + // Getting the highest possible oracle value + uint256 oracleValue = col.oracle.readUpper(); + + // Converting amount of agTokens in collateral and computing how much should be reimbursed to the user + // Amount is in `BASE_TOKENS` and the outputted collateral amount should be in collateral base + uint256 amountInC = (amount * col.collatBase) / oracleValue; + + // Computing how much of collateral can be redeemed by the user after taking fees + // The value of the fees here is `_computeFeeBurn(amount,col)` (it is a proportion expressed in `BASE_PARAMS`) + // The real value of what can be redeemed by the user is `amountInC * (BASE_PARAMS - fees) / BASE_PARAMS`, + // but we prefer to avoid doing multiplications after divisions + uint256 redeemInC = (amount * (BASE_PARAMS - _computeFeeBurn(amount, col)) * col.collatBase) / + (oracleValue * BASE_PARAMS); + require(redeemInC >= minCollatAmount, "15"); + + // Updating the `stocksUsers` that is the amount of collateral that was brought by users + col.stocksUsers -= amount; + + // Event needed to track `col.stocksUsers` off-chain + emit BurntStablecoins(address(poolManager), amount, redeemInC); + + // Computing the exact amount of fees from this transaction and accumulating it for SLPs + _updateSanRate(((amountInC - redeemInC) * col.slpData.feesForSLPs) / BASE_PARAMS, col); + + col.token.safeTransferFrom(address(poolManager), dest, redeemInC); + } + + // ============================== SLPs ========================================= + + /// @notice Lets a SLP enter the protocol by sending collateral to the system in exchange of sanTokens + /// @param user Address of the SLP to send sanTokens to + /// @param amount Amount of collateral sent + /// @param poolManager Address of the `PoolManager` of the required collateral + function deposit( + uint256 amount, + address user, + IPoolManager poolManager + ) external { + // Searching collateral data + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + _whenNotPaused(SLP, address(poolManager)); + _updateSanRate(0, col); + + // No overflow check needed for the amount since it's never casted to int and Solidity versions above 0.8.0 + // automatically handle overflows + col.token.safeTransferFrom(msg.sender, address(poolManager), amount); + col.sanToken.mint(user, (amount * BASE_TOKENS) / col.sanRate); + } + + /// @notice Lets a SLP burn of sanTokens and receive the corresponding collateral back in exchange at the + /// current exchange rate between sanTokens and collateral + /// @param amount Amount of sanTokens burnt by the SLP + /// @param burner Address that will burn its sanTokens + /// @param dest Address that will receive the collateral + /// @param poolManager Address of the `PoolManager` of the required collateral + /// @dev The `msg.sender` should have approval to burn from the `burner` or the `msg.sender` should be the `burner` + /// @dev This transaction will fail if the `PoolManager` does not have enough reserves, the front will however be here + /// to notify them that they cannot withdraw + /// @dev In case there are not enough reserves, strategies should be harvested or their debt ratios should be adjusted + /// by governance to make sure that users, HAs or SLPs withdrawing always have free collateral they can use + function withdraw( + uint256 amount, + address burner, + address dest, + IPoolManager poolManager + ) external { + Collateral storage col = collateralMap[poolManager]; + _contractMapCheck(col); + _whenNotPaused(SLP, address(poolManager)); + _updateSanRate(0, col); + + if (burner == msg.sender) { + col.sanToken.burnSelf(amount, burner); + } else { + col.sanToken.burnFrom(amount, burner, msg.sender); + } + // Computing the amount of collateral to give back to the SLP depending on slippage and on the `sanRate` + uint256 redeemInC = (amount * (BASE_PARAMS - col.slpData.slippage) * col.sanRate) / (BASE_TOKENS * BASE_PARAMS); + + col.token.safeTransferFrom(address(poolManager), dest, redeemInC); + } +} diff --git a/contracts/stableMaster/StableMasterInternal.sol b/contracts/stableMaster/StableMasterInternal.sol new file mode 100644 index 0000000..21bf8e9 --- /dev/null +++ b/contracts/stableMaster/StableMasterInternal.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./StableMasterStorage.sol"; + +/// @title StableMasterInternal +/// @author Angle Core Team +/// @notice `StableMaster` is the contract handling all the collateral types accepted for a given stablecoin +/// It does all the accounting and is the point of entry in the protocol for stable holders and seekers as well as SLPs +/// @dev This file contains all the internal function of the `StableMaster` contract +contract StableMasterInternal is StableMasterStorage, PausableMapUpgradeable { + /// @notice Checks if the `msg.sender` calling the contract has the right to do it + /// @param col Struct for the collateral associated to the caller address + /// @dev Since the `StableMaster` contract uses a `contractMap` that stores addresses of some verified + /// protocol's contracts in it, and since the roles corresponding to these addresses are never admin roles + /// it is cheaper not to use for these contracts OpenZeppelin's access control logic + /// @dev A non null associated token address is what is used to check if a `PoolManager` has well been initialized + /// @dev We could set `PERPETUALMANAGER_ROLE`, `POOLMANAGER_ROLE` and `FEEMANAGER_ROLE` for this + /// contract, but this would actually be inefficient + function _contractMapCheck(Collateral storage col) internal view { + require(address(col.token) != address(0), "3"); + } + + /// @notice Checks if the protocol has been paused for an agent and for a given collateral type for this + /// stablecoin + /// @param agent Name of the agent to check, it is either going to be `STABLE` or `SLP` + /// @param poolManager `PoolManager` contract for which to check pauses + function _whenNotPaused(bytes32 agent, address poolManager) internal view { + require(!paused[keccak256(abi.encodePacked(agent, poolManager))], "18"); + } + + /// @notice Updates the `sanRate` that is the exchange rate between sanTokens given to SLPs and collateral or + /// accumulates fees to be distributed to SLPs before doing it at next block + /// @param toShare Amount of interests that needs to be redistributed to the SLPs through the `sanRate` + /// @param col Struct for the collateral of interest here which values are going to be updated + /// @dev This function can only increase the `sanRate` and is not used to take into account a loss made through + /// lending or another yield farming strategy: this is done in the `signalLoss` function + /// @dev The `sanRate` is only be updated from the fees accumulated from previous blocks and the fees to share to SLPs + /// are just accumulated to be distributed at next block + /// @dev A flashloan attack could consist in seeing fees to be distributed, deposit, increase the `sanRate` and then + /// withdraw: what is done with the `lockedInterests` parameter is a way to mitigate that + /// @dev Another solution against flash loans would be to have a non null `slippage` at all times: this is far from ideal + /// for SLPs in the first place + function _updateSanRate(uint256 toShare, Collateral storage col) internal { + uint256 _lockedInterests = col.slpData.lockedInterests; + // Checking if the `sanRate` has been updated in the current block using past block fees + // This is a way to prevent flash loans attacks when an important amount of fees are going to be distributed + // in a block: fees are stored but will just be distributed to SLPs who will be here during next blocks + if (block.timestamp != col.slpData.lastBlockUpdated && _lockedInterests > 0) { + uint256 sanMint = col.sanToken.totalSupply(); + if (sanMint != 0) { + // Checking if the update is too important and should be made in multiple blocks + if (_lockedInterests > col.slpData.maxInterestsDistributed) { + // `sanRate` is expressed in `BASE_TOKENS` + col.sanRate += (col.slpData.maxInterestsDistributed * BASE_TOKENS) / sanMint; + _lockedInterests -= col.slpData.maxInterestsDistributed; + } else { + col.sanRate += (_lockedInterests * BASE_TOKENS) / sanMint; + _lockedInterests = 0; + } + emit SanRateUpdated(address(col.token), col.sanRate); + } else { + _lockedInterests = 0; + } + } + // Adding the fees to be distributed at next block + if (toShare != 0) { + if ((col.slpData.slippageFee == 0) && (col.slpData.feesAside != 0)) { + // If the collateral ratio is big enough, all the fees or gains will be used to update the `sanRate` + // If there were fees or lending gains that had been put aside, they will be added in this case to the + // update of the `sanRate` + toShare += col.slpData.feesAside; + col.slpData.feesAside = 0; + } else if (col.slpData.slippageFee != 0) { + // Computing the fraction of fees and gains that should be left aside if the collateral ratio is too small + uint256 aside = (toShare * col.slpData.slippageFee) / BASE_PARAMS; + toShare -= aside; + // The amount of fees left aside should be rounded above + col.slpData.feesAside += aside; + } + // Updating the amount of fees to be distributed next block + _lockedInterests += toShare; + } + col.slpData.lockedInterests = _lockedInterests; + col.slpData.lastBlockUpdated = block.timestamp; + } + + /// @notice Computes the current fees to be taken when minting using `amount` of collateral + /// @param amount Amount of collateral in the transaction to get stablecoins + /// @param col Struct for the collateral of interest + /// @return feeMint Mint Fees taken to users expressed in collateral + /// @dev Fees depend on the hedge ratio that is the ratio between what is hedged by HAs and what should be hedged + /// @dev The more is hedged by HAs, the smaller fees are expected to be + /// @dev Fees are also corrected by the `bonusMalusMint` parameter which induces a dependence in collateral ratio + function _computeFeeMint(uint256 amount, Collateral storage col) internal view returns (uint256 feeMint) { + uint64 feeMint64; + if (col.feeData.xFeeMint.length == 1) { + // This is done to avoid an external call in the case where the fees are constant regardless of the collateral + // ratio + feeMint64 = col.feeData.yFeeMint[0]; + } else { + uint64 hedgeRatio = _computeHedgeRatio(amount + col.stocksUsers, col); + // Computing the fees based on the spread + feeMint64 = _piecewiseLinear(hedgeRatio, col.feeData.xFeeMint, col.feeData.yFeeMint); + } + // Fees could in some occasions depend on other factors like collateral ratio + // Keepers are the ones updating this part of the fees + feeMint = (feeMint64 * col.feeData.bonusMalusMint) / BASE_PARAMS; + } + + /// @notice Computes the current fees to be taken when burning stablecoins + /// @param amount Amount of collateral corresponding to the stablecoins burnt in the transaction + /// @param col Struct for the collateral of interest + /// @return feeBurn Burn fees taken to users expressed in collateral + /// @dev The amount is obtained after the amount of agTokens sent is converted in collateral + /// @dev Fees depend on the hedge ratio that is the ratio between what is hedged by HAs and what should be hedged + /// @dev The more is hedged by HAs, the higher fees are expected to be + /// @dev Fees are also corrected by the `bonusMalusBurn` parameter which induces a dependence in collateral ratio + function _computeFeeBurn(uint256 amount, Collateral storage col) internal view returns (uint256 feeBurn) { + uint64 feeBurn64; + if (col.feeData.xFeeBurn.length == 1) { + // Avoiding an external call if fees are constant + feeBurn64 = col.feeData.yFeeBurn[0]; + } else { + uint64 hedgeRatio = _computeHedgeRatio(col.stocksUsers - amount, col); + // Computing the fees based on the spread + feeBurn64 = _piecewiseLinear(hedgeRatio, col.feeData.xFeeBurn, col.feeData.yFeeBurn); + } + // Fees could in some occasions depend on other factors like collateral ratio + // Keepers are the ones updating this part of the fees + feeBurn = (feeBurn64 * col.feeData.bonusMalusBurn) / BASE_PARAMS; + } + + /// @notice Computes the hedge ratio that is the ratio between the amount of collateral hedged by HAs + /// divided by the amount that should be hedged + /// @param newStocksUsers Value of the collateral from users to hedge + /// @param col Struct for the collateral of interest + /// @return ratio Ratio between what's hedged divided what's to hedge + /// @dev This function is typically called to compute mint or burn fees + /// @dev It seeks from the `PerpetualManager` contract associated to the collateral the total amount + /// already hedged by HAs and compares it to the amount to hedge + function _computeHedgeRatio(uint256 newStocksUsers, Collateral storage col) internal view returns (uint64 ratio) { + // Fetching the amount hedged by HAs from the corresponding `perpetualManager` contract + uint256 totalHedgeAmount = col.perpetualManager.totalHedgeAmount(); + newStocksUsers = (col.feeData.targetHAHedge * newStocksUsers) / BASE_PARAMS; + if (newStocksUsers > totalHedgeAmount) ratio = uint64((totalHedgeAmount * BASE_PARAMS) / newStocksUsers); + else ratio = uint64(BASE_PARAMS); + } +} diff --git a/contracts/stableMaster/StableMasterStorage.sol b/contracts/stableMaster/StableMasterStorage.sol new file mode 100644 index 0000000..4be19dc --- /dev/null +++ b/contracts/stableMaster/StableMasterStorage.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./StableMasterEvents.sol"; + +/// @title StableMasterStorage +/// @author Angle Core Team +/// @notice `StableMaster` is the contract handling all the collateral types accepted for a given stablecoin +/// It does all the accounting and is the point of entry in the protocol for stable holders and seekers as well as SLPs +/// @dev This file contains all the variables and parameters used in the `StableMaster` contract +contract StableMasterStorage is StableMasterEvents, FunctionUtils { + // All the details about a collateral that are going to be stored in `StableMaster` + struct Collateral { + // Interface for the token accepted by the underlying `PoolManager` contract + IERC20 token; + // Reference to the `SanToken` for the pool + ISanToken sanToken; + // Reference to the `PerpetualManager` for the pool + IPerpetualManager perpetualManager; + // Adress of the oracle for the change rate between + // collateral and the corresponding stablecoin + IOracle oracle; + // Amount of collateral in the reserves that comes from users + // converted in stablecoin value. Updated at minting and burning. + // A `stocksUsers` of 10 for a collateral type means that overall the balance of the collateral from users + // that minted/burnt stablecoins using this collateral is worth 10 of stablecoins + uint256 stocksUsers; + // Exchange rate between sanToken and collateral + uint256 sanRate; + // Base used in the collateral implementation (ERC20 decimal) + uint256 collatBase; + // Parameters for SLPs and update of the `sanRate` + SLPData slpData; + // All the fees parameters + MintBurnData feeData; + } + + // ============================ Variables and References ===================================== + + /// @notice Maps a `PoolManager` contract handling a collateral for this stablecoin to the properties of the struct above + mapping(IPoolManager => Collateral) public collateralMap; + + /// @notice Reference to the `AgToken` used in this `StableMaster` + /// This reference cannot be changed + IAgToken public agToken; + + // Maps a contract to an address corresponding to the `IPoolManager` address + // It is typically used to avoid passing in parameters the address of the `PerpetualManager` when `PerpetualManager` + // is calling `StableMaster` to get information + // It is the Access Control equivalent for the `SanToken`, `PoolManager`, `PerpetualManager` and `FeeManager` + // contracts associated to this `StableMaster` + mapping(address => IPoolManager) internal _contractMap; + + // List of all collateral managers + IPoolManager[] internal _managerList; + + // Reference to the `Core` contract of the protocol + ICore internal _core; +} diff --git a/contracts/strategies/BaseStrategy.sol b/contracts/strategies/BaseStrategy.sol new file mode 100644 index 0000000..450c219 --- /dev/null +++ b/contracts/strategies/BaseStrategy.sol @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./BaseStrategyEvents.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/// @title BaseStrategy +/// @author Forked from https://github.com/yearn/yearn-managers/blob/master/contracts/BaseStrategy.sol +/// @notice `BaseStrategy` implements all of the required functionalities to interoperate +/// with the `PoolManager` Contract. +/// @dev This contract should be inherited and the abstract methods implemented to adapt the `Strategy` +/// to the particular needs it has to create a return. +abstract contract BaseStrategy is BaseStrategyEvents, AccessControl { + using SafeERC20 for IERC20; + + uint256 public constant BASE = 10**18; + uint256 public constant SECONDSPERYEAR = 31556952; + + /// @notice Role for `PoolManager` only + bytes32 public constant POOLMANAGER_ROLE = keccak256("POOLMANAGER_ROLE"); + /// @notice Role for guardians and governors + bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); + + // ======================== References to contracts ============================ + + /// @notice Reference to the protocol's collateral `PoolManager` + IPoolManager public poolManager; + + /// @notice Reference to the ERC20 farmed by this strategy + IERC20 public want; + + /// @notice Base of the ERC20 token farmed by this strategy + uint256 public wantBase; + + //@notice Reference to the ERC20 distributed as a reward by the strategy + IERC20 public rewards; + + // ============================ Parameters ===================================== + + /// @notice The minimum number of seconds between harvest calls. See + /// `setMinReportDelay()` for more details + uint256 public minReportDelay; + + /// @notice The maximum number of seconds between harvest calls. See + /// `setMaxReportDelay()` for more details + uint256 public maxReportDelay; + + /// @notice Use this to adjust the threshold at which running a debt causes a + /// harvest trigger. See `setDebtThreshold()` for more details + uint256 public debtThreshold; + + /// @notice See note on `setEmergencyExit()` + bool public emergencyExit; + + /// @notice The minimum amount moved for a call to `havest` to + /// be "justifiable". See `setRewardAmountAndMinimumAmountMoved()` for more details + uint256 public minimumAmountMoved; + + /// @notice Reward obtained by calling harvest + /// @dev If this is null rewards are not currently being distributed + uint256 public rewardAmount; + + // ============================ Constructor ==================================== + + /// @notice Constructor of the `BaseStrategy` + /// @param _poolManager Address of the `PoolManager` lending collateral to this strategy + /// @param _rewards The token given to reward keepers + /// @param governorList List of the governor addresses of the protocol + /// @param guardian Address of the guardian + constructor( + address _poolManager, + IERC20 _rewards, + address[] memory governorList, + address guardian + ) { + poolManager = IPoolManager(_poolManager); + want = IERC20(poolManager.token()); + wantBase = 10**(IERC20Metadata(address(want)).decimals()); + require(guardian != address(0) && address(_rewards) != address(0), "0"); + // The token given as a reward to keepers should be different from the token handled by the + // strategy + require(address(_rewards) != address(want), "92"); + rewards = _rewards; + + // Initializing variables + minReportDelay = 0; + maxReportDelay = 86400; + debtThreshold = 100 * BASE; + minimumAmountMoved = 0; + rewardAmount = 0; + emergencyExit = false; + + // AccessControl + // Governor is guardian so no need for a governor role + // `PoolManager` is guardian as well to allow for more flexibility + _setupRole(POOLMANAGER_ROLE, address(_poolManager)); + for (uint256 i = 0; i < governorList.length; i++) { + require(governorList[i] != address(0), "0"); + _setupRole(GUARDIAN_ROLE, governorList[i]); + } + _setupRole(GUARDIAN_ROLE, guardian); + _setRoleAdmin(POOLMANAGER_ROLE, POOLMANAGER_ROLE); + _setRoleAdmin(GUARDIAN_ROLE, POOLMANAGER_ROLE); + + // Give `PoolManager` unlimited access (might save gas) + want.safeIncreaseAllowance(address(poolManager), type(uint256).max); + } + + // ========================== Core functions =================================== + + /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting + /// the Strategy's position. + /// @dev In the rare case the Strategy is in emergency shutdown, this will exit + /// the Strategy's position. + /// @dev When `harvest()` is called, the Strategy reports to the Manager (via + /// `poolManager.report()`), so in some cases `harvest()` must be called in order + /// to take in profits, to borrow newly available funds from the Manager, or + /// otherwise adjust its position. In other cases `harvest()` must be + /// called to report to the Manager on the Strategy's position, especially if + /// any losses have occurred. + /// @dev As keepers may directly profit from this function, there may be front-running problems with miners bots, + /// we may have to put an access control logic for this function to only allow white-listed addresses to act + /// as keepers for the protocol + function harvest() external { + uint256 profit = 0; + uint256 loss = 0; + uint256 debtOutstanding = poolManager.debtOutstanding(); + uint256 debtPayment = 0; + if (emergencyExit) { + // Free up as much capital as possible + uint256 amountFreed = _liquidateAllPositions(); + if (amountFreed < debtOutstanding) { + loss = debtOutstanding - amountFreed; + } else if (amountFreed > debtOutstanding) { + profit = amountFreed - debtOutstanding; + } + debtPayment = debtOutstanding - loss; + } else { + // Free up returns for Manager to pull + (profit, loss, debtPayment) = _prepareReturn(debtOutstanding); + } + emit Harvested(profit, loss, debtPayment, debtOutstanding); + + // Taking into account the rewards to distribute + // This should be done before reporting to the `PoolManager` + // because the `PoolManager` will update the params.lastReport of the strategy + if (rewardAmount > 0) { + uint256 lastReport = poolManager.strategies(address(this)).lastReport; + if ( + (block.timestamp - lastReport >= minReportDelay) && // Should not trigger if we haven't waited long enough since previous harvest + ((block.timestamp - lastReport >= maxReportDelay) || // If hasn't been called in a while + (debtPayment > debtThreshold) || // If the debt was too high + (loss > 0) || // If some loss occured + (minimumAmountMoved < want.balanceOf(address(this)) + profit)) // If the amount moved was significant + ) { + rewards.safeTransfer(msg.sender, rewardAmount); + } + } + + // Allows Manager to take up to the "harvested" balance of this contract, + // which is the amount it has earned since the last time it reported to + // the Manager. + poolManager.report(profit, loss, debtPayment); + + // Check if free returns are left, and re-invest them + _adjustPosition(); + } + + /// @notice Withdraws `_amountNeeded` to `poolManager`. + /// @param _amountNeeded How much `want` to withdraw. + /// @return amountFreed How much `want` withdrawn. + /// @return _loss Any realized losses + /// @dev This may only be called by the `PoolManager` + function withdraw(uint256 _amountNeeded) + external + onlyRole(POOLMANAGER_ROLE) + returns (uint256 amountFreed, uint256 _loss) + { + // Liquidate as much as possible `want` (up to `_amountNeeded`) + (amountFreed, _loss) = _liquidatePosition(_amountNeeded); + // Send it directly back (NOTE: Using `msg.sender` saves some gas here) + want.safeTransfer(msg.sender, amountFreed); + // NOTE: Reinvest anything leftover on next `tend`/`harvest` + } + + // ============================ View functions ================================= + + /// @notice Provides an accurate estimate for the total amount of assets + /// (principle + return) that this Strategy is currently managing, + /// denominated in terms of `want` tokens. + /// This total should be "realizable" e.g. the total value that could + /// *actually* be obtained from this Strategy if it were to divest its + /// entire position based on current on-chain conditions. + /// @return The estimated total assets in this Strategy. + /// @dev Care must be taken in using this function, since it relies on external + /// systems, which could be manipulated by the attacker to give an inflated + /// (or reduced) value produced by this function, based on current on-chain + /// conditions (e.g. this function is possible to influence through + /// flashloan attacks, oracle manipulations, or other DeFi attack + /// mechanisms). + function estimatedTotalAssets() public view virtual returns (uint256); + + /// @notice Provides an indication of whether this strategy is currently "active" + /// in that it is managing an active position, or will manage a position in + /// the future. This should correlate to `harvest()` activity, so that Harvest + /// events can be tracked externally by indexing agents. + /// @return True if the strategy is actively managing a position. + function isActive() public view returns (bool) { + return estimatedTotalAssets() > 0; + } + + /// @notice Provides a signal to the keeper that `harvest()` should be called. The + /// keeper will provide the estimated gas cost that they would pay to call + /// `harvest()`, and this function should use that estimate to make a + /// determination if calling it is "worth it" for the keeper. This is not + /// the only consideration into issuing this trigger, for example if the + /// position would be negatively affected if `harvest()` is not called + /// shortly, then this can return `true` even if the keeper might be "at a + /// loss" + /// @return `true` if `harvest()` should be called, `false` otherwise. + /// @dev `callCostInWei` must be priced in terms of `wei` (1e-18 ETH). + /// @dev See `min/maxReportDelay`, `debtThreshold` to adjust the + /// strategist-controlled parameters that will influence whether this call + /// returns `true` or not. These parameters will be used in conjunction + /// with the parameters reported to the Manager (see `params`) to determine + /// if calling `harvest()` is merited. + /// @dev This function has been tested in a branch different from the main branch + function harvestTrigger() external view virtual returns (bool) { + StrategyParams memory params = poolManager.strategies(address(this)); + + // Should not trigger if we haven't waited long enough since previous harvest + if (block.timestamp - params.lastReport < minReportDelay) return false; + + // Should trigger if hasn't been called in a while + if (block.timestamp - params.lastReport >= maxReportDelay) return true; + + // If some amount is owed, pay it back + // NOTE: Since debt is based on deposits, it makes sense to guard against large + // changes to the value from triggering a harvest directly through user + // behavior. This should ensure reasonable resistance to manipulation + // from user-initiated withdrawals as the outstanding debt fluctuates. + uint256 outstanding = poolManager.debtOutstanding(); + + if (outstanding > debtThreshold) return true; + + // Check for profits and losses + uint256 total = estimatedTotalAssets(); + // Trigger if we have a loss to report + + if (total + debtThreshold < params.totalStrategyDebt) return true; + + uint256 profit = 0; + if (total > params.totalStrategyDebt) profit = total - params.totalStrategyDebt; // We've earned a profit! + + // Otherwise, only trigger if it "makes sense" economically (gas cost + // is = _debtPayment + _profit`). + /// + /// `_debtOutstanding` will be 0 if the Strategy is not past the configured + /// debt limit, otherwise its value will be how far past the debt limit + /// the Strategy is. The Strategy's debt limit is configured in the Manager. + /// + /// NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`. + /// It is okay for it to be less than `_debtOutstanding`, as that + /// should only used as a guide for how much is left to pay back. + /// Payments should be made to minimize loss from slippage, debt, + /// withdrawal fees, etc. + /// + /// See `poolManager.debtOutstanding()`. + function _prepareReturn(uint256 _debtOutstanding) + internal + virtual + returns ( + uint256 _profit, + uint256 _loss, + uint256 _debtPayment + ); + + /// @notice Performs any adjustments to the core position(s) of this Strategy given + /// what change the Manager made in the "investable capital" available to the + /// Strategy. Note that all "free capital" in the Strategy after the report + /// was made is available for reinvestment. Also note that this number + /// could be 0, and you should handle that scenario accordingly. + function _adjustPosition() internal virtual; + + /// @notice Liquidates up to `_amountNeeded` of `want` of this strategy's positions, + /// irregardless of slippage. Any excess will be re-invested with `_adjustPosition()`. + /// This function should return the amount of `want` tokens made available by the + /// liquidation. If there is a difference between them, `_loss` indicates whether the + /// difference is due to a realized loss, or if there is some other sitution at play + /// (e.g. locked funds) where the amount made available is less than what is needed. + /// + /// NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained + function _liquidatePosition(uint256 _amountNeeded) + internal + virtual + returns (uint256 _liquidatedAmount, uint256 _loss); + + /// @notice Liquidates everything and returns the amount that got freed. + /// This function is used during emergency exit instead of `_prepareReturn()` to + /// liquidate all of the Strategy's positions back to the Manager. + function _liquidateAllPositions() internal virtual returns (uint256 _amountFreed); + + /// @notice Override this to add all tokens/tokenized positions this contract + /// manages on a *persistent* basis (e.g. not just for swapping back to + /// want ephemerally). + /// + /// NOTE: Do *not* include `want`, already included in `sweep` below. + /// + /// Example: + /// ``` + /// function _protectedTokens() internal override view returns (address[] memory) { + /// address[] memory protected = new address[](3); + /// protected[0] = tokenA; + /// protected[1] = tokenB; + /// protected[2] = tokenC; + /// return protected; + /// } + /// ``` + function _protectedTokens() internal view virtual returns (address[] memory); + + // ============================== Governance =================================== + + /// @notice Activates emergency exit. Once activated, the Strategy will exit its + /// position upon the next harvest, depositing all funds into the Manager as + /// quickly as is reasonable given on-chain conditions. + /// @dev This may only be called by the `PoolManager`, because when calling this the `PoolManager` should at the same + /// time update the debt ratio + /// @dev This function can only be called once by the `PoolManager` contract + /// @dev See `poolManager.setEmergencyExit()` and `harvest()` for further details. + function setEmergencyExit() external onlyRole(POOLMANAGER_ROLE) { + emergencyExit = true; + emit EmergencyExitActivated(); + } + + /// @notice Used to change `rewards`. + /// @param _rewards The address to use for pulling rewards. + function setRewards(IERC20 _rewards) external onlyRole(GUARDIAN_ROLE) { + require(address(_rewards) != address(0) && address(_rewards) != address(want), "92"); + rewards = _rewards; + emit UpdatedRewards(address(_rewards)); + } + + /// @notice Used to change the reward amount and the `minimumAmountMoved` parameter + /// @param _rewardAmount The new amount of reward given to keepers + /// @param _minimumAmountMoved The new minimum amount of collateral moved for a call to `harvest` to be + /// considered profitable and justifying a reward given to the keeper calling the function + /// @dev A null reward amount corresponds to reward distribution being deactivated + function setRewardAmountAndMinimumAmountMoved(uint256 _rewardAmount, uint256 _minimumAmountMoved) + external + onlyRole(GUARDIAN_ROLE) + { + rewardAmount = _rewardAmount; + minimumAmountMoved = _minimumAmountMoved; + emit UpdatedRewardAmountAndMinimumAmountMoved(_rewardAmount, _minimumAmountMoved); + } + + /// @notice Used to change `minReportDelay`. `minReportDelay` is the minimum number + /// of blocks that should pass for `harvest()` to be called. + /// @param _delay The minimum number of seconds to wait between harvests. + /// @dev For external keepers (such as the Keep3r network), this is the minimum + /// time between jobs to wait. (see `harvestTrigger()` + /// for more details.) + function setMinReportDelay(uint256 _delay) external onlyRole(GUARDIAN_ROLE) { + minReportDelay = _delay; + emit UpdatedMinReportDelayed(_delay); + } + + /// @notice Used to change `maxReportDelay`. `maxReportDelay` is the maximum number + /// of blocks that should pass for `harvest()` to be called. + /// @param _delay The maximum number of seconds to wait between harvests. + /// @dev For external keepers (such as the Keep3r network), this is the maximum + /// time between jobs to wait. (see `harvestTrigger()` + /// for more details.) + function setMaxReportDelay(uint256 _delay) external onlyRole(GUARDIAN_ROLE) { + maxReportDelay = _delay; + emit UpdatedMaxReportDelayed(_delay); + } + + /// @notice Sets how far the Strategy can go into loss without a harvest and report + /// being required. + /// @param _debtThreshold How big of a loss this Strategy may carry without + /// @dev By default this is 0, meaning any losses would cause a harvest which + /// will subsequently report the loss to the Manager for tracking. (See + /// `harvestTrigger()` for more details.) + function setDebtThreshold(uint256 _debtThreshold) external onlyRole(GUARDIAN_ROLE) { + debtThreshold = _debtThreshold; + emit UpdatedDebtThreshold(_debtThreshold); + } + + /// @notice Removes tokens from this Strategy that are not the type of tokens + /// managed by this Strategy. This may be used in case of accidentally + /// sending the wrong kind of token to this Strategy. + /// + /// Tokens will be sent to `governance()`. + /// + /// This will fail if an attempt is made to sweep `want`, or any tokens + /// that are protected by this Strategy. + /// + /// This may only be called by governance. + /// @param _token The token to transfer out of this `PoolManager`. + /// @param to Address to send the tokens to. + /// @dev + /// Implement `_protectedTokens()` to specify any additional tokens that + /// should be protected from sweeping in addition to `want`. + function sweep(address _token, address to) external onlyRole(GUARDIAN_ROLE) { + require(_token != address(want), "93"); + + address[] memory __protectedTokens = _protectedTokens(); + for (uint256 i = 0; i < __protectedTokens.length; i++) + // In the strategy we use so far, the only protectedToken is the want token + // and this has been checked above + require(_token != __protectedTokens[i], "93"); + + IERC20(_token).safeTransfer(to, IERC20(_token).balanceOf(address(this))); + } + + // ============================ Manager functions ============================== + + /// @notice Adds a new guardian address and echoes the change to the contracts + /// that interact with this collateral `PoolManager` + /// @param _guardian New guardian address + /// @dev This internal function has to be put in this file because Access Control is not defined + /// in PoolManagerInternal + function addGuardian(address _guardian) external virtual; + + /// @notice Revokes the guardian role and propagates the change to other contracts + /// @param guardian Old guardian address to revoke + function revokeGuardian(address guardian) external virtual; +} diff --git a/contracts/strategies/BaseStrategyEvents.sol b/contracts/strategies/BaseStrategyEvents.sol new file mode 100644 index 0000000..13f4662 --- /dev/null +++ b/contracts/strategies/BaseStrategyEvents.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "../external/AccessControl.sol"; + +import "../interfaces/IStrategy.sol"; +import "../interfaces/IPoolManager.sol"; + +/// @title BaseStrategyEvents +/// @author Angle Core Team +/// @notice Events used in the abstract `BaseStrategy` contract +contract BaseStrategyEvents { + // So indexers can keep track of this + event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding); + + event UpdatedMinReportDelayed(uint256 delay); + + event UpdatedMaxReportDelayed(uint256 delay); + + event UpdatedDebtThreshold(uint256 debtThreshold); + + event UpdatedRewards(address rewards); + + event UpdatedIsRewardActivated(bool activated); + + event UpdatedRewardAmountAndMinimumAmountMoved(uint256 _rewardAmount, uint256 _minimumAmountMoved); + + event EmergencyExitActivated(); +} diff --git a/contracts/strategies/Strategy.sol b/contracts/strategies/Strategy.sol new file mode 100644 index 0000000..d4cbb19 --- /dev/null +++ b/contracts/strategies/Strategy.sol @@ -0,0 +1,479 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./StrategyEvents.sol"; + +/// @title Strategy +/// @author Forked from https://github.com/Grandthrax/yearnV2-generic-lender-strat +/// @notice A lender optimisation strategy for any ERC20 asset +/// @dev This strategy works by taking plugins designed for standard lending platforms +/// It automatically chooses the best yield generating platform and adjusts accordingly +/// The adjustment is sub optimal so there is an additional option to manually set position +contract Strategy is StrategyEvents, BaseStrategy { + using SafeERC20 for IERC20; + using Address for address; + + // ======================== References to contracts ============================ + + IGenericLender[] public lenders; + + // ======================== Parameters ========================================= + + uint256 public withdrawalThreshold; + + // ============================== Constructor ================================== + + /// @notice Constructor of the `Strategy` + /// @param _poolManager Address of the `PoolManager` lending to this strategy + /// @param _rewards The token given to reward keepers. + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + constructor( + address _poolManager, + IERC20 _rewards, + address[] memory governorList, + address guardian + ) BaseStrategy(_poolManager, _rewards, governorList, guardian) { + withdrawalThreshold = 1000 * wantBase; + } + + // ========================== Internal Mechanics =============================== + + /// @notice Frees up profit plus `_debtOutstanding`. + /// @param _debtOutstanding Amount to withdraw + /// @return _profit Profit freed by the call + /// @return _loss Loss discovered by the call + /// @return _debtPayment Amount freed to reimburse the debt + /// @dev If `_debtOutstanding` is more than we can free we get as much as possible. + function _prepareReturn(uint256 _debtOutstanding) + internal + override + returns ( + uint256 _profit, + uint256 _loss, + uint256 _debtPayment + ) + { + _profit = 0; + _loss = 0; //for clarity + _debtPayment = _debtOutstanding; + + uint256 lentAssets = lentTotalAssets(); + + uint256 looseAssets = want.balanceOf(address(this)); + + uint256 total = looseAssets + lentAssets; + + if (lentAssets == 0) { + // No position to harvest or profit to report + if (_debtPayment > looseAssets) { + // We can only return looseAssets + _debtPayment = looseAssets; + } + + return (_profit, _loss, _debtPayment); + } + + uint256 debt = poolManager.strategies(address(this)).totalStrategyDebt; + + if (total > debt) { + _profit = total - debt; + + uint256 amountToFree = _profit + _debtPayment; + // We need to add outstanding to our profit + // don't need to do logic if there is nothing to free + if (amountToFree > 0 && looseAssets < amountToFree) { + // Withdraw what we can withdraw + _withdrawSome(amountToFree - looseAssets); + uint256 newLoose = want.balanceOf(address(this)); + + // If we dont have enough money adjust _debtOutstanding and only change profit if needed + if (newLoose < amountToFree) { + if (_profit > newLoose) { + _profit = newLoose; + _debtPayment = 0; + } else { + _debtPayment = Math.min(newLoose - _profit, _debtPayment); + } + } + } + } else { + // Serious loss should never happen but if it does lets record it accurately + _loss = debt - total; + + uint256 amountToFree = _loss + _debtPayment; + if (amountToFree > 0 && looseAssets < amountToFree) { + // Withdraw what we can withdraw + + _withdrawSome(amountToFree - looseAssets); + uint256 newLoose = want.balanceOf(address(this)); + + // If we dont have enough money adjust `_debtOutstanding` and only change profit if needed + if (newLoose < amountToFree) { + if (_loss > newLoose) { + _loss = newLoose; + _debtPayment = 0; + } else { + _debtPayment = Math.min(newLoose - _loss, _debtPayment); + } + } + } + } + } + + /// @notice Estimates highest and lowest apr lenders among a `lendersList` + /// @param lendersList List of all the lender contracts associated to this strategy + /// @return _lowest The index of the lender in the `lendersList` with lowest apr + /// @return _lowestApr The lowest apr + /// @return _highest The index of the lender with highest apr + /// @return _potential The potential apr of this lender if funds are moved from lowest to highest + /// @dev `lendersList` is kept as a parameter to avoid multiplying reads in storage to the `lenders` + /// array + function _estimateAdjustPosition(IGenericLender[] memory lendersList) + internal + view + returns ( + uint256 _lowest, + uint256 _lowestApr, + uint256 _highest, + uint256 _potential + ) + { + //all loose assets are to be invested + uint256 looseAssets = want.balanceOf(address(this)); + + // our simple algo + // get the lowest apr strat + // cycle through and see who could take its funds plus want for the highest apr + _lowestApr = type(uint256).max; + _lowest = 0; + uint256 lowestNav = 0; + + uint256 highestApr = 0; + _highest = 0; + + for (uint256 i = 0; i < lendersList.length; i++) { + uint256 aprAfterDeposit = lendersList[i].aprAfterDeposit(looseAssets); + if (aprAfterDeposit > highestApr) { + highestApr = aprAfterDeposit; + _highest = i; + } + + if (lendersList[i].hasAssets()) { + uint256 apr = lendersList[i].apr(); + if (apr < _lowestApr) { + _lowestApr = apr; + _lowest = i; + lowestNav = lendersList[i].nav(); + } + } + } + + //if we can improve apr by withdrawing we do so + _potential = lendersList[_highest].aprAfterDeposit(lowestNav + looseAssets); + } + + /// @notice Function called by keepers to adjust the position + /// @dev The algorithm moves assets from lowest return to highest + /// like a very slow idiot bubble sort + function _adjustPosition() internal override { + // Emergency exit is dealt with at beginning of harvest + if (emergencyExit) { + return; + } + // Storing the `lenders` array in a cache variable + IGenericLender[] memory lendersList = lenders; + // We just keep all money in want if we dont have any lenders + if (lendersList.length == 0) { + return; + } + + (uint256 lowest, uint256 lowestApr, uint256 highest, uint256 potential) = _estimateAdjustPosition(lendersList); + + if (potential > lowestApr) { + // Apr should go down after deposit so won't be withdrawing from self + lendersList[lowest].withdrawAll(); + } + + uint256 bal = want.balanceOf(address(this)); + if (bal > 0) { + want.safeTransfer(address(lendersList[highest]), bal); + lendersList[highest].deposit(); + } + } + + /// @notice Withdraws a given amount from lenders + /// @param _amount The amount to withdraw + /// @dev Cycle through withdrawing from worst rate first + function _withdrawSome(uint256 _amount) internal returns (uint256 amountWithdrawn) { + IGenericLender[] memory lendersList = lenders; + if (lendersList.length == 0) { + return 0; + } + + // Don't withdraw dust + if (_amount < withdrawalThreshold) { + return 0; + } + + amountWithdrawn = 0; + // In most situations this will only run once. Only big withdrawals will be a gas guzzler + uint256 j = 0; + while (amountWithdrawn < _amount) { + uint256 lowestApr = type(uint256).max; + uint256 lowest = 0; + for (uint256 i = 0; i < lendersList.length; i++) { + if (lendersList[i].hasAssets()) { + uint256 apr = lendersList[i].apr(); + if (apr < lowestApr) { + lowestApr = apr; + lowest = i; + } + } + } + if (!lendersList[lowest].hasAssets()) { + return amountWithdrawn; + } + amountWithdrawn = amountWithdrawn + lendersList[lowest].withdraw(_amount - amountWithdrawn); + j++; + // To avoid want infinite loop + if (j >= 6) { + return amountWithdrawn; + } + } + } + + /// @notice Liquidates up to `_amountNeeded` of `want` of this strategy's positions, + /// irregardless of slippage. Any excess will be re-invested with `_adjustPosition()`. + /// This function should return the amount of `want` tokens made available by the + /// liquidation. If there is a difference between them, `_loss` indicates whether the + /// difference is due to a realized loss, or if there is some other sitution at play + /// (e.g. locked funds) where the amount made available is less than what is needed. + /// + /// NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained + function _liquidatePosition(uint256 _amountNeeded) internal override returns (uint256 _amountFreed, uint256 _loss) { + uint256 _balance = want.balanceOf(address(this)); + + if (_balance >= _amountNeeded) { + //if we don't set reserve here withdrawer will be sent our full balance + return (_amountNeeded, 0); + } else { + uint256 received = _withdrawSome(_amountNeeded - _balance) + (_balance); + if (received >= _amountNeeded) { + return (_amountNeeded, 0); + } else { + return (received, 0); + } + } + } + + /// @notice Liquidates everything and returns the amount that got freed. + /// This function is used during emergency exit instead of `_prepareReturn()` to + /// liquidate all of the Strategy's positions back to the Manager. + function _liquidateAllPositions() internal override returns (uint256 _amountFreed) { + (_amountFreed, ) = _liquidatePosition(estimatedTotalAssets()); + } + + // ========================== View Functions =================================== + + struct LendStatus { + string name; + uint256 assets; + uint256 rate; + address add; + } + + /// @notice View function to check the current state of the strategy + /// @return Returns the status of all lenders attached the strategy + function lendStatuses() external view returns (LendStatus[] memory) { + uint256 lendersListLength = lenders.length; + LendStatus[] memory statuses = new LendStatus[](lendersListLength); + for (uint256 i = 0; i < lendersListLength; i++) { + LendStatus memory s; + s.name = lenders[i].lenderName(); + s.add = address(lenders[i]); + s.assets = lenders[i].nav(); + s.rate = lenders[i].apr(); + statuses[i] = s; + } + return statuses; + } + + /// @notice View function to check the total assets lent + function lentTotalAssets() public view returns (uint256) { + uint256 nav = 0; + for (uint256 i = 0; i < lenders.length; i++) { + nav = nav + lenders[i].nav(); + } + return nav; + } + + /// @notice View function to check the total assets managed by the strategy + function estimatedTotalAssets() public view override returns (uint256 nav) { + nav = lentTotalAssets() + want.balanceOf(address(this)); + } + + /// @notice View function to check the number of lending platforms + function numLenders() external view returns (uint256) { + return lenders.length; + } + + /// @notice The weighted apr of all lenders. sum(nav * apr)/totalNav + function estimatedAPR() external view returns (uint256) { + uint256 bal = estimatedTotalAssets(); + if (bal == 0) { + return 0; + } + + uint256 weightedAPR = 0; + + for (uint256 i = 0; i < lenders.length; i++) { + weightedAPR = weightedAPR + lenders[i].weightedApr(); + } + + return weightedAPR / bal; + } + + /// @notice Prevents the governance from withdrawing want tokens + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](1); + protected[0] = address(want); + return protected; + } + + // ============================ Governance ===================================== + + struct LenderRatio { + address lender; + //share x 1000 + uint16 share; + } + + /// @notice Reallocates all funds according to a new distributions + /// @param _newPositions List of shares to specify the new allocation + /// @dev Share must add up to 1000. 500 means 50% etc + /// @dev This code has been forked, so we have not thoroughly tested it on our own + function manualAllocation(LenderRatio[] memory _newPositions) external onlyRole(GUARDIAN_ROLE) { + IGenericLender[] memory lendersList = lenders; + uint256 share = 0; + for (uint256 i = 0; i < lendersList.length; i++) { + lendersList[i].withdrawAll(); + } + + uint256 assets = want.balanceOf(address(this)); + + for (uint256 i = 0; i < _newPositions.length; i++) { + bool found = false; + + //might be annoying and expensive to do this second loop but worth it for safety + for (uint256 j = 0; j < lendersList.length; j++) { + if (address(lendersList[j]) == _newPositions[i].lender) { + found = true; + } + } + require(found, "94"); + + share = share + _newPositions[i].share; + uint256 toSend = (assets * _newPositions[i].share) / 1000; + want.safeTransfer(_newPositions[i].lender, toSend); + IGenericLender(_newPositions[i].lender).deposit(); + } + + require(share == 1000, "95"); + } + + /// @notice Changes the withdrawal threshold + /// @param _threshold The new withdrawal threshold + /// @dev governor, guardian or `PoolManager` only + function setWithdrawalThreshold(uint256 _threshold) external onlyRole(GUARDIAN_ROLE) { + withdrawalThreshold = _threshold; + } + + /// @notice Add lenders for the strategy to choose between + /// @param newLender The adapter to the added lending platform + /// @dev Governor, guardian or `PoolManager` only + function addLender(IGenericLender newLender) external onlyRole(GUARDIAN_ROLE) { + require(newLender.strategy() == address(this), "96"); + + for (uint256 i = 0; i < lenders.length; i++) { + require(address(newLender) != address(lenders[i]), "97"); + } + lenders.push(newLender); + + emit AddLender(address(newLender)); + } + + /// @notice Removes a lending platform and fails if total withdrawal is impossible + /// @param lender The address of the adapter to the lending platform to remove + function safeRemoveLender(address lender) external onlyRole(GUARDIAN_ROLE) { + _removeLender(lender, false); + } + + /// @notice Removes a lending platform and even if total withdrawal is impossible + /// @param lender The address of the adapter to the lending platform to remove + function forceRemoveLender(address lender) external onlyRole(GUARDIAN_ROLE) { + _removeLender(lender, true); + } + + /// @notice Internal function to handle lending platform removing + /// @param lender The address of the adapter for the lending platform to remove + /// @param force Whether it is required that all the funds are withdrawn prior to removal + function _removeLender(address lender, bool force) internal { + IGenericLender[] memory lendersList = lenders; + for (uint256 i = 0; i < lendersList.length; i++) { + if (lender == address(lendersList[i])) { + bool allWithdrawn = lendersList[i].withdrawAll(); + + if (!force) { + require(allWithdrawn, "98"); + } + + // Put the last index here + // then remove last index + if (i != lendersList.length - 1) { + lenders[i] = lendersList[lendersList.length - 1]; + } + + // Pop shortens array by 1 thereby deleting the last index + lenders.pop(); + + // If balance to spend we might as well put it into the best lender + if (want.balanceOf(address(this)) > 0) { + _adjustPosition(); + } + + emit RemoveLender(lender); + + return; + } + } + require(false, "94"); + } + + // ========================== Manager functions ================================ + + /// @notice Adds a new guardian address and echoes the change to the contracts + /// that interact with this collateral `PoolManager` + /// @param _guardian New guardian address + /// @dev This internal function has to be put in this file because `AccessControl` is not defined + /// in `PoolManagerInternal` + function addGuardian(address _guardian) external override onlyRole(POOLMANAGER_ROLE) { + // Granting the new role + // Access control for this contract + _grantRole(GUARDIAN_ROLE, _guardian); + // Propagating the new role in other contract + for (uint256 i = 0; i < lenders.length; i++) { + lenders[i].grantRole(GUARDIAN_ROLE, _guardian); + } + } + + /// @notice Revokes the guardian role and propagates the change to other contracts + /// @param guardian Old guardian address to revoke + function revokeGuardian(address guardian) external override onlyRole(POOLMANAGER_ROLE) { + _revokeRole(GUARDIAN_ROLE, guardian); + for (uint256 i = 0; i < lenders.length; i++) { + lenders[i].revokeRole(GUARDIAN_ROLE, guardian); + } + } +} diff --git a/contracts/strategies/StrategyEvents.sol b/contracts/strategies/StrategyEvents.sol new file mode 100644 index 0000000..0bfaedd --- /dev/null +++ b/contracts/strategies/StrategyEvents.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "./BaseStrategy.sol"; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; +import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; + +import "../interfaces/IGenericLender.sol"; +import "../interfaces/IOracle.sol"; + +/// @title StrategyEvents +/// @author Angle Core Team +/// @notice Events used in `Strategy` contracts +contract StrategyEvents { + event AddLender(address indexed lender); + + event RemoveLender(address indexed lender); +} diff --git a/contracts/strategies/StrategyStETHAcc.sol b/contracts/strategies/StrategyStETHAcc.sol new file mode 100644 index 0000000..8f996a6 --- /dev/null +++ b/contracts/strategies/StrategyStETHAcc.sol @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.7; + +import "../interfaces/external/curve/Curve.sol"; +import "../interfaces/external/lido/ISteth.sol"; +import "../interfaces/IWETH.sol"; +import "./BaseStrategy.sol"; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +/// @title StrategyStETHAcc +/// @author Forked from https://github.com/Grandthrax/yearn-steth-acc/blob/master/contracts/Strategy.sol +/// @notice A strategy designed to getting yield on wETH by putting ETH in Lido or Curve for stETH and exiting +/// for wETH +contract StrategyStETHAcc is BaseStrategy { + using SafeERC20 for IERC20; + using Address for address; + + /// @notice Current `apr` of the strategy: this apr needs to be manually filled by the strategist + /// and updated when Lido's APR changes. It is put like that as there is no easy way to compute Lido's APR + /// on-chain + uint256 public apr; + + /// @notice Reference to the Curve ETH/stETH + ICurveFi public immutable stableSwapSTETH; + /// @notice Reference to wETH, it should normally be equal to `want` + IWETH public immutable weth; + /// @notice Reference to the stETH token + ISteth public immutable stETH; + + address private _referral = 0x16388463d60FFE0661Cf7F1f31a7D658aC790ff7; //stratms. for recycling and redepositing + /// @notice Maximum trade size within the strategy + uint256 public maxSingleTrade; + /// @notice Parameter used for slippage protection + uint256 public constant DENOMINATOR = 10_000; + /// @notice Slippage parameter for the swaps on Curve: out of `DENOMINATOR` + uint256 public slippageProtectionOut; // = 50; //out of 10000. 50 = 0.5% + + /// @notice ID of wETH in the Curve pool + int128 private constant _WETHID = 0; + /// @notice ID of stETH in the Curve pool + int128 private constant _STETHID = 1; + + /// @notice Constructor of the `Strategy` + /// @param _poolManager Address of the `PoolManager` lending to this strategy + /// @param _rewards The token given to reward keepers. + /// @param governorList List of addresses with governor privilege + /// @param guardian Address of the guardian + /// @param _stableSwapSTETH Address of the stETH/ETH Curve pool + /// @param _weth Address of wETH + /// @param _stETH Address of the stETH token + constructor( + address _poolManager, + IERC20 _rewards, + address[] memory governorList, + address guardian, + address _stableSwapSTETH, + address _weth, + ISteth _stETH + ) BaseStrategy(_poolManager, _rewards, governorList, guardian) { + require(address(want) == _weth, "20"); + stableSwapSTETH = ICurveFi(_stableSwapSTETH); + weth = IWETH(_weth); + stETH = ISteth(_stETH); + _stETH.approve(_stableSwapSTETH, type(uint256).max); + maxSingleTrade = 1_000 * 1e18; + slippageProtectionOut = 50; + } + + /// @notice This contract gets ETH and so it needs this function + receive() external payable {} + + // ========================== View Functions =================================== + + /// @notice View function to check the total assets managed by the strategy + /// @dev We are purposely treating stETH and ETH as being equivalent. + /// This is for a few reasons. The main one is that we do not have a good way to value + /// stETH at any current time without creating exploit routes. + /// Currently you can mint eth for steth but can't burn steth for eth so need to sell. + /// Once eth 2.0 is merged you will be able to burn 1-1 as well. + /// The main downside here is that we will noramlly overvalue our position as we expect stETH + /// to trade slightly below peg. That means we will earn profit on deposits and take losses on withdrawals. + /// This may sound scary but it is the equivalent of using virtualprice in a curve lp. + /// As we have seen from many exploits, virtual pricing is safer than touch pricing. + function estimatedTotalAssets() public view override returns (uint256) { + return stethBalance() + wantBalance(); + } + + /// @notice Returns the wETH balance of the strategy + function wantBalance() public view returns (uint256) { + return want.balanceOf(address(this)); + } + + /// @notice Returns the stETH balance of the strategy + function stethBalance() public view returns (uint256) { + return stETH.balanceOf(address(this)); + } + + /// @notice The ETH APR of owning stETH + function estimatedAPR() external view returns (uint256) { + return apr; + } + + // ========================== Strategy Functions =============================== + + /// @notice Frees up profit plus `_debtOutstanding`. + /// @param _debtOutstanding Amount to withdraw + /// @return _profit Profit freed by the call + /// @return _loss Loss discovered by the call + /// @return _debtPayment Amount freed to reimburse the debt: it is an amount made available for the `PoolManager` + /// @dev If `_debtOutstanding` is more than we can free we get as much as possible. + function _prepareReturn(uint256 _debtOutstanding) + internal + override + returns ( + uint256 _profit, + uint256 _loss, + uint256 _debtPayment + ) + { + uint256 wantBal = wantBalance(); + uint256 stethBal = stethBalance(); + uint256 totalAssets = wantBal + stethBal; + + uint256 debt = poolManager.strategies(address(this)).totalStrategyDebt; + + if (totalAssets >= debt) { + _profit = totalAssets - debt; + + uint256 toWithdraw = _profit + _debtOutstanding; + // If more should be withdrawn than what's in the strategy: we divest from Curve + if (toWithdraw > wantBal) { + // We step our withdrawals. Adjust max single trade to withdraw more + uint256 willWithdraw = Math.min(maxSingleTrade, toWithdraw); + uint256 withdrawn = _divest(willWithdraw); + if (withdrawn < willWithdraw) { + _loss = willWithdraw - withdrawn; + } + } + wantBal = wantBalance(); + + // Computing net off profit and loss + if (_profit >= _loss) { + _profit = _profit - _loss; + _loss = 0; + } else { + _profit = 0; + _loss = _loss - _profit; + } + + // profit + _debtOutstanding must be <= wantbalance. Prioritise profit first + if (wantBal < _profit) { + _profit = wantBal; + } else if (wantBal < toWithdraw) { + _debtPayment = wantBal - _profit; + } else { + _debtPayment = _debtOutstanding; + } + } else { + _loss = debt - totalAssets; + } + } + + /// @notice Liquidates everything and returns the amount that got freed. + /// This function is used during emergency exit instead of `_prepareReturn()` to + /// liquidate all of the Strategy's positions back to the Manager. + function _liquidateAllPositions() internal override returns (uint256 _amountFreed) { + _divest(stethBalance()); + _amountFreed = wantBalance(); + } + + /// @notice Function called when harvesting to invest in stETH + function _adjustPosition() internal override { + uint256 toInvest = wantBalance(); + if (toInvest > 0) { + uint256 realInvest = Math.min(maxSingleTrade, toInvest); + _invest(realInvest); + } + } + + /// @notice Invests `_amount` wETH in stETH + /// @param _amount Amount of wETH to put in stETH + /// @return The amount of stETH received from the investment + /// @dev This function chooses the optimal route between going to Lido directly or doing a swap on Curve + /// @dev This function automatically wraps wETH to ETH + function _invest(uint256 _amount) internal returns (uint256) { + uint256 before = stethBalance(); + // Unwrapping the tokens + weth.withdraw(_amount); + // Test if we should buy from Curve instead of minting from Lido + uint256 out = stableSwapSTETH.get_dy(_WETHID, _STETHID, _amount); + if (out < _amount) { + // If we get less than one stETH per wETH we use Lido + stETH.submit{ value: _amount }(_referral); + } else { + // Otherwise, we do a Curve swap + stableSwapSTETH.exchange{ value: _amount }(_WETHID, _STETHID, _amount, _amount); + } + + return stethBalance() - before; + } + + /// @notice Divests stETH on Curve and gets wETH back to the strategy in exchange + /// @param _amount Amount of stETH to divest + /// @dev Curve is the only place to convert stETH to ETH + function _divest(uint256 _amount) internal returns (uint256) { + uint256 before = wantBalance(); + + // Computing slippage protection for the swap + uint256 slippageAllowance = (_amount * (DENOMINATOR - slippageProtectionOut)) / DENOMINATOR; + // Curve swap + stableSwapSTETH.exchange(_STETHID, _WETHID, _amount, slippageAllowance); + + weth.deposit{ value: address(this).balance }(); + + return wantBalance() - before; + } + + /// @notice Attempts to withdraw `_amountNeeded` from the strategy and lets the user decide if they take the loss or not + /// @param _amountNeeded Amount to withdraw from the strategy + function _liquidatePosition(uint256 _amountNeeded) + internal + override + returns (uint256 _liquidatedAmount, uint256 _loss) + { + uint256 wantBal = wantBalance(); + if (wantBal < _amountNeeded) { + uint256 toWithdraw = _amountNeeded - wantBal; + uint256 withdrawn = _divest(toWithdraw); + if (withdrawn < toWithdraw) { + _loss = toWithdraw - withdrawn; + } + } + + _liquidatedAmount = _amountNeeded - _loss; + } + + // NOTE: Can override `tendTrigger` and `harvestTrigger` if necessary + + // Override this to add all tokens/tokenized positions this contract manages + // on a *persistent* basis (e.g. not just for swapping back to want ephemerally) + // NOTE: Do *not* include `want`, already included in `sweep` below + // + // Example: + // + // function _protectedTokens() internal override view returns (address[] memory) { + // address[] memory protected = new address[](3); + // protected[0] = tokenA; + // protected[1] = tokenB; + // protected[2] = tokenC; + // return protected; + // } + function _protectedTokens() internal view override returns (address[] memory) { + address[] memory protected = new address[](1); + protected[0] = address(stETH); + + return protected; + } + + // ============================ Governance ===================================== + + /// @notice Updates the referral code for Lido + /// @param newReferral Address of the new referral + function updateReferral(address newReferral) public onlyRole(GUARDIAN_ROLE) { + _referral = newReferral; + } + + /// @notice Updates the size of a trade in the strategy + /// @param _maxSingleTrade New `maxSingleTrade` value + function updateMaxSingleTrade(uint256 _maxSingleTrade) public onlyRole(GUARDIAN_ROLE) { + maxSingleTrade = _maxSingleTrade; + } + + /// @notice Changes the estimated APR of the strategy + /// @param _apr New strategy APR + function setApr(uint256 _apr) public onlyRole(GUARDIAN_ROLE) { + apr = _apr; + } + + /// @notice Updates the maximum slippage protection parameter + /// @param _slippageProtectionOut New slippage protection parameter + function updateSlippageProtectionOut(uint256 _slippageProtectionOut) public onlyRole(GUARDIAN_ROLE) { + slippageProtectionOut = _slippageProtectionOut; + } + + /// @notice Invests `_amount` in stETH + /// @param _amount Amount to invest + /// @dev This function allows to override the behavior that could be obtained through `harvest` calls + function invest(uint256 _amount) external onlyRole(GUARDIAN_ROLE) { + require(wantBalance() >= _amount); + uint256 realInvest = Math.min(maxSingleTrade, _amount); + _invest(realInvest); + } + + /// @notice Rescues stuck ETH from the strategy + /// @dev This strategy should never have stuck eth, but let it just in case + function rescueStuckEth() external onlyRole(GUARDIAN_ROLE) { + weth.deposit{ value: address(this).balance }(); + } + + // ========================== Manager functions ================================ + + /// @notice Adds a new guardian address and echoes the change to the contracts + /// that interact with this collateral `PoolManager` + /// @param _guardian New guardian address + /// @dev This internal function has to be put in this file because `AccessControl` is not defined + /// in `PoolManagerInternal` + function addGuardian(address _guardian) external override onlyRole(POOLMANAGER_ROLE) { + // Granting the new role + // Access control for this contract + _grantRole(GUARDIAN_ROLE, _guardian); + } + + /// @notice Revokes the guardian role and propagates the change to other contracts + /// @param guardian Old guardian address to revoke + function revokeGuardian(address guardian) external override onlyRole(POOLMANAGER_ROLE) { + _revokeRole(GUARDIAN_ROLE, guardian); + } +} diff --git a/contracts/utils/FunctionUtils.sol b/contracts/utils/FunctionUtils.sol new file mode 100644 index 0000000..2b5ab2b --- /dev/null +++ b/contracts/utils/FunctionUtils.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title FunctionUtils +/// @author Angle Core Team +/// @notice Contains all the utility functions that are needed in different places of the protocol +/// @dev Functions in this contract should typically be pure functions +/// @dev This contract is voluntarily a contract and not a library to save some gas cost every time it is used +contract FunctionUtils { + /// @notice Base that is used to compute ratios and floating numbers + uint256 public constant BASE_TOKENS = 10**18; + /// @notice Base that is used to define parameters that need to have a floating value (for instance parameters + /// that are defined as ratios) + uint256 public constant BASE_PARAMS = 10**9; + + /// @notice Computes the value of a linear by part function at a given point + /// @param x Point of the function we want to compute + /// @param xArray List of breaking points (in ascending order) that define the linear by part function + /// @param yArray List of values at breaking points (not necessarily in ascending order) + /// @dev The evolution of the linear by part function between two breaking points is linear + /// @dev Before the first breaking point and after the last one, the function is constant with a value + /// equal to the first or last value of the yArray + /// @dev This function is relevant if `x` is between O and `BASE_PARAMS`. If `x` is greater than that, then + /// everything will be as if `x` is equal to the greater element of the `xArray` + function _piecewiseLinear( + uint64 x, + uint64[] memory xArray, + uint64[] memory yArray + ) internal pure returns (uint64) { + if (x >= xArray[xArray.length - 1]) { + return yArray[xArray.length - 1]; + } else if (x <= xArray[0]) { + return yArray[0]; + } else { + uint256 lower; + uint256 upper = xArray.length - 1; + uint256 mid; + while (upper - lower > 1) { + mid = lower + (upper - lower) / 2; + if (xArray[mid] <= x) { + lower = mid; + } else { + upper = mid; + } + } + if (yArray[upper] > yArray[lower]) { + // There is no risk of overflow here as in the product of the difference of `y` + // with the difference of `x`, the product is inferior to `BASE_PARAMS**2` which does not + // overflow for `uint64` + return + yArray[lower] + + ((yArray[upper] - yArray[lower]) * (x - xArray[lower])) / + (xArray[upper] - xArray[lower]); + } else { + return + yArray[lower] - + ((yArray[lower] - yArray[upper]) * (x - xArray[lower])) / + (xArray[upper] - xArray[lower]); + } + } + } + + /// @notice Checks if the input arrays given by governance to update the fee structure is valid + /// @param xArray List of breaking points (in ascending order) that define the linear by part function + /// @param yArray List of values at breaking points (not necessarily in ascending order) + /// @dev This function is a way to avoid some governance attacks or errors + /// @dev The modifier checks if the arrays have a non null length, if their length is the same, if the values + /// in the `xArray` are in ascending order and if the values in the `xArray` and in the `yArray` are not superior + /// to `BASE_PARAMS` + modifier onlyCompatibleInputArrays(uint64[] memory xArray, uint64[] memory yArray) { + require(xArray.length == yArray.length && xArray.length > 0, "5"); + for (uint256 i = 0; i <= yArray.length - 1; i++) { + require(yArray[i] <= uint64(BASE_PARAMS) && xArray[i] <= uint64(BASE_PARAMS), "6"); + if (i > 0) { + require(xArray[i] > xArray[i - 1], "7"); + } + } + _; + } + + /// @notice Checks if the new value given for the parameter is consistent (it should be inferior to 1 + /// if it corresponds to a ratio) + /// @param fees Value of the new parameter to check + modifier onlyCompatibleFees(uint64 fees) { + require(fees <= BASE_PARAMS, "4"); + _; + } + + /// @notice Checks if the new address given is not null + /// @param newAddress Address to check + /// @dev Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation + modifier zeroCheck(address newAddress) { + require(newAddress != address(0), "0"); + _; + } +} diff --git a/contracts/utils/OracleMath.sol b/contracts/utils/OracleMath.sol new file mode 100644 index 0000000..3e89e0b --- /dev/null +++ b/contracts/utils/OracleMath.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "../external/FullMath.sol"; + +/// @title OracleMath +/// @author Forked and adapted by Angle Core Team from https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/TickMath.sol +/// @notice Math library for computing prices from ticks +/// @dev Computes price for ticks of size 1.0001, i.e. sqrt(1.0001^tick). Supports +/// prices between 2**-128 and 2**128 +contract OracleMath is FullMath { + /// @dev Maximum tick that may be passed to `_getSqrtRatioAtTick` computed from log base 1.0001 of 2**128 + int24 internal constant _MAX_TICK = 887272; + + /// @notice Given a tick and a token amount, calculates the amount of token received in exchange + /// @param tick Tick value used to calculate the quote + /// @param baseAmount Amount of token to be converted + /// @param multiply Boolean representing whether the `baseToken` has a lower address than the `quoteToken` + /// @return quoteAmount Amount of `quoteToken` received for `baseAmount` of `baseToken` + function _getQuoteAtTick( + int24 tick, + uint256 baseAmount, + uint256 multiply + ) internal pure returns (uint256 quoteAmount) { + uint256 ratio = _getRatioAtTick(tick); + + quoteAmount = (multiply == 1) ? _mulDiv(ratio, baseAmount, 1e18) : _mulDiv(1e18, baseAmount, ratio); + } + + /// @notice Calculates 1.0001^tick * in out ERC20 decimals + /// @dev Adapted from Uniswap `_getSqrtRatioAtTick` but we don't consider the square root + /// anymore but directly the full rate + /// @dev Throws if `|tick| > max tick` + /// @param tick The input tick for the above formula + /// @return rate uint256 representing the ratio of the two assets `(token1/token0) * 10**decimals(token1)` + /// at the given tick + function _getRatioAtTick(int24 tick) internal pure returns (uint256 rate) { + uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); + require(absTick <= uint256(int256(_MAX_TICK)), "T"); + + uint256 ratio = absTick & 0x1 != 0 ? 0xfff97272373d413259a46990580e213a : 0x100000000000000000000000000000000; + if (absTick & 0x2 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; + if (absTick & 0x4 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; + if (absTick & 0x8 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; + if (absTick & 0x10 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; + if (absTick & 0x20 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; + if (absTick & 0x40 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; + if (absTick & 0x80 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; + if (absTick & 0x100 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; + if (absTick & 0x200 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; + if (absTick & 0x400 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; + if (absTick & 0x800 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; + if (absTick & 0x1000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; + if (absTick & 0x2000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; + if (absTick & 0x4000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; + if (absTick & 0x8000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; + if (absTick & 0x10000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; + if (absTick & 0x20000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; + if (absTick & 0x40000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; + if (absTick & 0x80000 != 0) ratio = (ratio * 0x149b34ee7ac262) >> 128; + + if (tick > 0) ratio = type(uint256).max / ratio; + + // We need to modify the 96 decimal to be able to convert it to a D256 + // 2**59 ~ 10**18 (thus we guarantee the same precision) and 128-59 = 69 + // We retrieve a Q128.59 decimal. --> we have 69 bits free to reach the uint256 limit. + // Now, 2**69 >> 10**18 so we are safe in the Decimal conversion. + + uint256 price = uint256((ratio >> 69) + (ratio % (1 << 69) == 0 ? 0 : 1)); + rate = ((price * 1e18) >> 59); + } +} diff --git a/contracts/utils/PausableMapUpgradeable.sol b/contracts/utils/PausableMapUpgradeable.sol new file mode 100644 index 0000000..5154023 --- /dev/null +++ b/contracts/utils/PausableMapUpgradeable.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +/// @title PausableMap +/// @author Angle Core Team after a fork from OpenZeppelin's similar Pausable Contracts +/// @notice Contract module which allows children to implement an emergency stop +/// mechanism that can be triggered by an authorized account. +/// @notice It generalizes Pausable from OpenZeppelin by allowing to specify a bytes32 that +/// should be stopped +/// @dev This module is used through inheritance +/// @dev In Angle's protocol, this contract is mainly used in `StableMasterFront` +/// to prevent SLPs and new stable holders from coming in +/// @dev The modifiers `whenNotPaused` and `whenPaused` from the original OpenZeppelin contracts were removed +/// to save some space and because they are not used in the `StableMaster` contract where this contract +/// is imported +contract PausableMapUpgradeable { + /// @dev Emitted when the pause is triggered for `name` + event Paused(bytes32 name); + + /// @dev Emitted when the pause is lifted for `name` + event Unpaused(bytes32 name); + + /// @dev Mapping between a name and a boolean representing the paused state + mapping(bytes32 => bool) public paused; + + /// @notice Triggers stopped state for `name` + /// @param name Name for which to pause the contract + /// @dev The contract must not be paused for `name` + function _pause(bytes32 name) internal { + require(!paused[name], "18"); + paused[name] = true; + emit Paused(name); + } + + /// @notice Returns to normal state for `name` + /// @param name Name for which to unpause the contract + /// @dev The contract must be paused for `name` + function _unpause(bytes32 name) internal { + require(paused[name], "19"); + paused[name] = false; + emit Unpaused(name); + } +} diff --git a/errorMessages.json b/errorMessages.json new file mode 100644 index 0000000..1cbfeaa --- /dev/null +++ b/errorMessages.json @@ -0,0 +1,117 @@ +{ + "0": "zero address", + "1": "incorrect caller", + "2": "nonexistent perpetual", + "3": "invalid call", + "4": "incorrect value", + "5": "incorrect array length", + "6": "too big array values", + "7": "incorrect x array values", + "8": "incompatible parameters", + "9": "incorrect reference", + "10": "incorrect poolManager", + "11": "invalid oracle base", + "12": "incorrect oracle", + "13": "deployed", + "14": "incorrect feeManager", + "15": "too big slippage", + "16": "too many stablecoins issued", + "17": "stocksUsers too small", + "18": "paused", + "19": "not paused", + "20": "invalid token", + "21": "caller not approved", + "22": "reward too high", + "23": "burn amount exceeds allowance", + "24": "non ERC721Receiver", + "25": "too much collateral hedged", + "26": "transfer to the zero address", + "27": "zero value", + "28": "too big oracle rate", + "29": "too small margin", + "30": "too high leverage", + "31": "invalid timestamp", + "32": "too small cash out amount", + "33": "invalid conditions", + "34": "forceCashOut disabled", + "35": "approval to owner", + "36": "approval to caller", + "37": "incorrect y array values", + "38": "incompatible slippage and slippageFee arrays", + "39": "guardian cannot be governor", + "40": "incorrect address", + "41": "incorrect guardian", + "42": "invalid lists length", + "43": "incorrect governor", + "44": "stableMaster previously deployed", + "45": "incorrect stablecoin", + "46": "governor already added", + "47": "must have at least one governor", + "48": "governor not in the list", + "49": "wrong new guardian", + "50": "incorrect amount to pay", + "51": "oracle required", + "52": "already a reference", + "53": "incorrect start price", + "54": "incorrect amount", + "55": "not enough token left to sell", + "56": "incorrect soldToken balance", + "57": "invalid claim time", + "58": "base amounts not computed", + "59": "settlement already activated", + "60": "invalid proportion", + "61": "too many stablecoins claimed", + "62": "base amounts already computed", + "63": "invalid redeem time", + "64": "perpetual already claimed", + "65": "ratios cannot be modified after start", + "66": "too high amount", + "67": "only the minter can change the minter address", + "68": "only the minter can mint", + "69": "minting not allowed yet", + "70": "exceeded mint cap", + "71": "AccessControl: can only renounce roles for self", + "72": "incorrect freed amount by strategy", + "73": "strategy already added", + "74": "strategy not bound to this PoolManager", + "75": "strategy not linked to the right token", + "76": "debt ratio above one", + "77": "strategy still managing some funds", + "78": "invalid strategy", + "79": "only owner", + "80": "invalid staking contract", + "81": "not passed drip frequency", + "82": "no rewards", + "83": "incompatible reward tokens", + "84": "incorrect rewards distributor", + "85": "null duration", + "86": "too high frequency", + "87": "frequency exceeds duration", + "88": "invalid amount to distribute", + "89": "cannot withdraw 0", + "90": "cannot stake 0", + "91": "provided reward too high", + "92": "incorrect reward address", + "93": "protected token", + "94": "invalid lender", + "95": "invalid shares", + "96": "undocked lender", + "97": "already added", + "98": "withdrawal failed", + "99": "overflow", + "100": "invalid Chainlink rate", + "101": "incorrect guardians", + "102": "too large twap period", + "103": "incorrect Uniswap circuit", + "104": "incompatible lengths", + "105": "incorrect Chainlink pool", + "106": "incorrect Chainlink circuit length", + "107": "invalid size addressInAndOut", + "108": "too soon", + "109": "distributions are off", + "110": "gauge not activated yet or killed", + "111": "invalid path", + "112": "gauge already activated", + "113": "middleman: bridge must be zero address" +} + diff --git a/hardhat.config.ts b/hardhat.config.ts new file mode 100644 index 0000000..b2940b5 --- /dev/null +++ b/hardhat.config.ts @@ -0,0 +1,170 @@ +/// ENVVAR +// - ENABLE_GAS_REPORT +// - CI +// - RUNS +import 'dotenv/config'; + +import yargs from 'yargs'; +import { nodeUrl, accounts } from './utils/network'; +import { HardhatUserConfig } from 'hardhat/config'; + +import 'hardhat-contract-sizer'; +import 'hardhat-spdx-license-identifier'; +import 'hardhat-docgen'; +import 'hardhat-deploy'; +import 'hardhat-abi-exporter'; +import '@nomiclabs/hardhat-ethers'; +import '@nomiclabs/hardhat-solhint'; +import '@openzeppelin/hardhat-upgrades'; +import 'solidity-coverage'; +import '@typechain/hardhat'; + +const argv = yargs + .env('') + .boolean('enableGasReport') + .boolean('ci') + .number('runs') + .boolean('fork') + .boolean('disableAutoMining') + .parseSync(); + +if (argv.enableGasReport) { + import('hardhat-gas-reporter'); // eslint-disable-line +} + +const config: HardhatUserConfig = { + solidity: { + compilers: [ + { + version: '0.8.7', + settings: { + optimizer: { + enabled: true, + runs: 1000000, + }, + // debug: { revertStrings: 'strip' }, + }, + }, + ], + }, + defaultNetwork: 'hardhat', + networks: { + hardhat: { + accounts: accounts('mainnet'), + live: argv.fork || false, + blockGasLimit: 125e5, + initialBaseFeePerGas: 0, + hardfork: 'london', + forking: { + enabled: argv.fork || false, + url: nodeUrl('fork'), + // This is the last block before the deployer role is removed + // blockNumber: 13473325, + }, + mining: argv.disableAutoMining + ? { + auto: false, + interval: 1000, + } + : { auto: true }, + chainId: 1337, + }, + kovan: { + live: false, + url: nodeUrl('kovan'), + accounts: accounts('kovan'), + gas: 12e6, + gasPrice: 1e9, + chainId: 42, + }, + rinkeby: { + live: true, + url: nodeUrl('rinkeby'), + accounts: accounts('rinkeby'), + gas: 'auto', + // gasPrice: 12e8, + chainId: 4, + }, + goerli: { + live: true, + url: nodeUrl('goerli'), + accounts: accounts('goerli'), + gas: 12e6, + chainId: 5, + }, + mumbai: { + url: nodeUrl('mumbai'), + accounts: accounts('mumbai'), + gas: 'auto', + }, + polygon: { + url: nodeUrl('polygon'), + accounts: accounts('polygon'), + gas: 'auto', + }, + mainnet: { + live: true, + url: nodeUrl('mainnet'), + accounts: accounts('mainnet'), + gas: 'auto', + gasMultiplier: 1.3, + chainId: 1, + }, + angleTestNet: { + url: nodeUrl('angle'), + accounts: accounts('angle'), + gas: 12e6, + gasPrice: 5e9, + }, + }, + paths: { + sources: './contracts', + tests: './test', + }, + namedAccounts: { + deployer: 0, + guardian: 1, + user: 2, + slp: 3, + ha: 4, + keeper: 5, + user2: 6, + slp2: 7, + ha2: 8, + keeper2: 9, + }, + mocha: { + timeout: 100000, + retries: argv.ci ? 10 : 0, + }, + contractSizer: { + alphaSort: true, + runOnCompile: false, + disambiguatePaths: false, + }, + gasReporter: { + currency: 'USD', + outputFile: argv.ci ? 'gas-report.txt' : undefined, + }, + spdxLicenseIdentifier: { + overwrite: true, + runOnCompile: false, + }, + docgen: { + path: './docs', + clear: true, + runOnCompile: false, + }, + abiExporter: { + path: './export/abi', + clear: true, + flat: true, + spacing: 2, + }, + typechain: { + outDir: 'typechain', + target: 'ethers-v5', + }, +}; + +export default config; diff --git a/package.json b/package.json new file mode 100644 index 0000000..58d8a9c --- /dev/null +++ b/package.json @@ -0,0 +1,95 @@ +{ + "name": "angle-strategies", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "compile": "hardhat compile", + "coverage": "hardhat coverage", + "etherscan:mainnet": "hardhat --network mainnet etherscan-verify", + "etherscan:rinkeby": "hardhat --network rinkeby etherscan-verify", + "doc": "hardhat docgen", + "docify": "node docify.js", + "license": "hardhat prepend-spdx-license", + "lint": "yarn lint:js:fix && yarn lint:sol", + "lint:js:fix": "eslint --ignore-path .gitignore --fix --max-warnings 30 'scripts/**/*.ts' 'test/**/*.{js,ts}' 'deploy/*.{js,ts}' '*.{js,ts}'", + "lint:sol": "solhint --fix --max-warnings 20 \"contracts/**/*.sol\"", + "prettier": "yarn prettier:js && yarn prettier:sol", + "prettier:sol": "prettier --write 'contracts/**/*.sol'", + "prettier:js": "prettier --write 'scripts/**/*.ts' 'scripts/*.ts' 'test/**/*.{js,ts}' 'deploy/*.{js,ts}' '*.{js,ts}'", + "size": "hardhat size-contracts", + "test": "hardhat test", + "test:end:fork": "FORK=true hardhat test test/end-to-end/**.ts", + "test:gas": "ENABLE_GAS_REPORT=true CI=true hardhat test", + "test:fork:gas": "ENABLE_GAS_REPORT=true CI=true hardhat test --network localhost" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/AngleProtocol/Angle_Solidity.git" + }, + "keywords": [], + "author": "Angle Core Team", + "license": "GPL-3.0", + "bugs": { + "url": "https://github.com/AngleProtocol/Angle_Solidity/issues" + }, + "homepage": "https://github.com/AngleProtocol/Angle_Solidity#readme", + "devDependencies": { + "@angleprotocol/sdk": "1.0.38", + "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers", + "@nomiclabs/hardhat-solhint": "2.0.0", + "@nomiclabs/hardhat-web3": "2.0.0", + "@openzeppelin/contracts": "4.5.0", + "@openzeppelin/contracts-upgradeable": "4.5.1", + "@openzeppelin/hardhat-upgrades": "1.14.0", + "@openzeppelin/test-helpers": "0.5.15", + "@typechain/ethers-v5": "9.0.0", + "@typechain/hardhat": "4.0.0", + "@types/chai": "^4.2.21", + "@types/chai-as-promised": "^7.1.4", + "@types/fs-extra": "^9.0.13", + "@types/mocha": "^9.0.0", + "@types/node": "^17.0.17", + "@types/yargs": "17.0.8", + "@typescript-eslint/eslint-plugin": "5.11.0", + "@typescript-eslint/parser": "5.11.0", + "@uniswap/v3-core": "^1.0.1", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", + "chai-bn": "0.3.1", + "dotenv": "16.0.0", + "eslint": "8.9.0", + "eslint-config-prettier": "^8.3.0", + "eslint-config-standard": "16.0.3", + "eslint-plugin-import": "2.25.4", + "eslint-plugin-mocha-no-only": "1.1.1", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-standard": "5.0.0", + "ethereum-waffle": "^3.4.0", + "ethers": "5.5.4", + "hardhat": "2.8.4", + "hardhat-abi-exporter": "2.8.0", + "hardhat-contract-sizer": "2.4.0", + "hardhat-deploy": "0.10.5", + "hardhat-docgen": "1.3.0", + "hardhat-gas-reporter": "1.0.4", + "hardhat-spdx-license-identifier": "2.0.3", + "mocha": "9.0.2", + "prettier": "2.5.1", + "prettier-plugin-solidity": "1.0.0-beta.19", + "solhint": "3.3.7", + "solhint-plugin-prettier": "0.0.5", + "solidity-coverage": "0.7.19", + "ts-node": "10.5.0", + "typechain": "7.0.0", + "typescript": "4.5.5", + "yargs": "^17.2.1" + }, + "dependencies": { + "dayjs": "^1.10.7", + "fs-extra": "^10.0.0", + "solc": "0.8.7" + } +} diff --git a/test/genericLender/GenericAave.test.js b/test/genericLender/GenericAave.test.js new file mode 100644 index 0000000..8e68375 --- /dev/null +++ b/test/genericLender/GenericAave.test.js @@ -0,0 +1,448 @@ +require('@openzeppelin/test-helpers/src/setup'); +const { ZERO_ADDRESS } = require('@openzeppelin/test-helpers/src/constants'); +const expectEvent = require('@openzeppelin/test-helpers/src/expectEvent'); +const { BN } = require('@openzeppelin/test-helpers/src/setup'); +const { + // utils + ether, + expectRevert, + expect, + BASE_ORACLE, + BASE, + gwei, + GenericAave, + MockOracle, + MockAave, + MockUniswapV3Router, + MockUniswapV2Router, + MockProtocolDataProvider, + Strategy, + // functions + initAngle, + initCollateral, + MAX_UINT256, +} = require('../helpers'); + +// Start test block +contract('GenericAave', accounts => { + const [governor, guardian, user, tester] = accounts; + before(async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + this.oracleETHWant = await MockOracle.new(BASE_ORACLE, new BN('18')); + this.aaveContract = await MockAave.new('AAVE', 'AAVE', this.wBTC.address); + this.aaveContract.deployNewUnderlying(this.wBTC.address); + this.uniswapV3Router = await MockUniswapV3Router.new(this.aaveContract.address, this.wBTC.address); + this.uniswapV2Router = await MockUniswapV2Router.new(new BN('10')); + this.strategy = await Strategy.new(this.managerBTC.address, this.ANGLE.address, [governor], guardian); + this.protocolDataProvider = await MockProtocolDataProvider.new(this.aaveContract.address); + this.params = { + aToken: this.aaveContract.address, + protocolDataProvider: this.protocolDataProvider.address, + stkAave: this.aaveContract.address, + aave: this.aaveContract.address, + }; + + this.genericAave = await GenericAave.new( + this.strategy.address, + 'aave', + this.uniswapV3Router.address, + this.uniswapV2Router.address, + this.params, + false, + web3.utils.asciiToHex('0'), + [governor], + guardian, + ); + + await this.strategy.addLender(this.genericAave.address, { from: governor }); + + await this.managerBTC.addStrategy(this.strategy.address, gwei('0.8'), { from: governor }); + // For easier testing: + await this.genericAave.grantRole(web3.utils.soliditySha3('STRATEGY_ROLE'), tester, { from: governor }); + this.guardianRole = web3.utils.soliditySha3('GUARDIAN_ROLE'); + this.guardianError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.guardianRole}`; + this.strategyRole = web3.utils.soliditySha3('STRATEGY_ROLE'); + this.strategyError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.strategyRole}`; + }); + + describe('Initialization', () => { + describe('Parameters', () => { + it('uniswapV3Router', async () => { + expect(await this.genericAave.uniswapV3Router()).to.be.equal(this.uniswapV3Router.address); + }); + it('uniswapV2Router', async () => { + expect(await this.genericAave.uniswapV2Router()).to.be.equal(this.uniswapV2Router.address); + }); + it('aToken', async () => { + expect(await this.genericAave.aToken()).to.be.equal(this.aaveContract.address); + }); + it('protocolDataProvider', async () => { + expect(await this.genericAave.protocolDataProvider()).to.be.equal(this.protocolDataProvider.address); + }); + it('stkAave', async () => { + expect(await this.genericAave.stkAave()).to.be.equal(this.aaveContract.address); + }); + it('aave', async () => { + expect(await this.genericAave.aave()).to.be.equal(this.aaveContract.address); + }); + it('path', async () => { + expect(await this.genericAave.path()).to.be.equal(web3.utils.asciiToHex('0')); + }); + it('isIncentivised', async () => { + expect(await this.genericAave.isIncentivised()).to.be.equal(false); + }); + it('lenderName', async () => { + expect(await this.genericAave.lenderName()).to.be.equal('aave'); + }); + it('poolManager', async () => { + expect(await this.genericAave.poolManager()).to.be.equal(this.managerBTC.address); + }); + it('strategy', async () => { + expect(await this.genericAave.strategy()).to.be.equal(this.strategy.address); + }); + it('want', async () => { + expect(await this.genericAave.want()).to.be.equal(this.wBTC.address); + }); + }); + describe('Access Control', () => { + it('deposit - reverts nonStrategy', async () => { + await expectRevert(this.genericAave.deposit({ from: user }), this.strategyError); + }); + it('withdraw - reverts nonStrategy', async () => { + await expectRevert(this.genericAave.withdraw(new BN('1'), { from: user }), this.strategyError); + }); + it('withdrawAll - reverts nonStrategy', async () => { + await expectRevert(this.genericAave.withdrawAll({ from: user }), this.strategyError); + }); + it('setPath - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.setPath(web3.utils.asciiToHex('0'), { from: user }), this.guardianError); + }); + it('emergencyWithdraw - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.emergencyWithdraw(new BN('1'), { from: user }), this.guardianError); + }); + it('sweep - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.sweep(this.aaveContract.address, user, { from: user }), this.guardianError); + }); + it('setReferralCode - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.setReferralCode(new BN('1'), { from: user }), this.guardianError); + }); + it('setIsIncentivised - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.setIsIncentivised(false, { from: user }), this.guardianError); + }); + it('startCooldown - reverts nonGuardian', async () => { + await expectRevert(this.genericAave.startCooldown({ from: user }), this.guardianError); + }); + }); + describe('constructor', () => { + it('reverts - zero uniswapV3 address', async () => { + await expectRevert( + GenericAave.new( + this.strategy.address, + 'aave', + ZERO_ADDRESS, + this.uniswapV2Router.address, + this.params, + false, + web3.utils.asciiToHex('0'), + [governor], + guardian, + ), + '0', + ); + }); + it('reverts - zero uniswapV2 address', async () => { + await expectRevert( + GenericAave.new( + this.strategy.address, + 'aave', + this.uniswapV3Router.address, + ZERO_ADDRESS, + this.params, + false, + web3.utils.asciiToHex('0'), + [governor], + guardian, + ), + '0', + ); + }); + it('reverts - zero stkAave address', async () => { + this.params = { + aToken: this.aaveContract.address, + protocolDataProvider: this.protocolDataProvider.address, + stkAave: ZERO_ADDRESS, + aave: this.aaveContract.address, + }; + await expectRevert( + GenericAave.new( + this.strategy.address, + 'aave', + this.uniswapV3Router.address, + this.uniswapV2Router.address, + this.params, + false, + web3.utils.asciiToHex('0'), + [governor], + guardian, + ), + '0', + ); + }); + it('reverts - zero aToken address', async () => { + this.params = { + aToken: ZERO_ADDRESS, + protocolDataProvider: this.protocolDataProvider.address, + stkAave: this.aaveContract.address, + aave: this.aaveContract.address, + }; + await expectRevert.unspecified( + GenericAave.new( + this.strategy.address, + 'aave', + this.uniswapV3Router.address, + this.uniswapV2Router.address, + this.params, + false, + web3.utils.asciiToHex('0'), + [governor], + guardian, + ), + ); + }); + }); + }); + + describe('setIsIncentivised', () => { + it('harvestTrigger - returns false', async () => { + expect(await this.genericAave.harvestTrigger()).to.be.equal(false); + }); + it('harvest - reverts - conditions are not met', async () => { + await expectRevert(this.genericAave.harvest(), 'conditions are not met'); + }); + it('apr - null', async () => { + expect(await this.genericAave.apr()).to.be.bignumber.equal(new BN('0')); + }); + it('success - parameter updated', async () => { + await this.genericAave.setIsIncentivised(true, { from: guardian }); + expect(await this.genericAave.isIncentivised()).to.be.equal(true); + }); + it('harvest - null stkAave balance', async () => { + await this.genericAave.harvest(); + }); + }); + + describe('hasAssets', () => { + it('success', async () => { + expect(await this.genericAave.hasAssets()).to.be.equal(false); + }); + }); + + describe('withdrawAll', () => { + it('success', async () => { + await this.genericAave.withdrawAll({ from: tester }); + }); + }); + + describe('apr', () => { + it('startCooldown', async () => { + await this.genericAave.startCooldown({ from: guardian }); + }); + }); + + describe('setPath', () => { + it('success', async () => { + await this.genericAave.setPath(web3.utils.asciiToHex('1'), { from: guardian }); + expect(await this.genericAave.path()).to.be.equal(web3.utils.asciiToHex('1')); + }); + }); + + describe('nav', () => { + it('success', async () => { + expect(await this.genericAave.nav()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('underlyingBalanceStored', () => { + it('success', async () => { + expect(await this.genericAave.underlyingBalanceStored()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('apr', () => { + it('success', async () => { + expect(await this.genericAave.apr()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('weightedApr', () => { + it('success', async () => { + expect(await this.genericAave.weightedApr()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('aprAfterDeposit', () => { + it('success', async () => { + await this.aaveContract.setDistributionEnd(new BN('0')); + expect(await this.genericAave.aprAfterDeposit(new BN('1'))).to.be.bignumber.equal( + ether('0.04').div(new BN('1000000000')), + ); + }); + }); + + describe('sweep', () => { + it('reverts - protected token', async () => { + await this.ANGLE.mint(this.genericAave.address, ether('1')); + await expectRevert(this.genericAave.sweep(this.aaveContract.address, user, { from: governor }), '93'); + }); + + it('success - balance updated', async () => { + await this.genericAave.sweep(this.ANGLE.address, user, { from: governor }); + expect(await this.ANGLE.balanceOf(user)).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('deposit', () => { + it('success', async () => { + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.deposit({ from: tester }); + expect(await this.wBTC.balanceOf(this.genericAave.address)).to.be.bignumber.equal(ether('0')); + expect(await this.aaveContract.balanceOf(this.genericAave.address)).to.be.bignumber.equal(ether('1')); + }); + it('hasAssets - success', async () => { + expect(await this.genericAave.hasAssets()).to.be.equal(true); + }); + }); + describe('setReferralCode', () => { + it('success', async () => { + const receipt = await this.genericAave.setReferralCode(new BN('10'), { from: guardian }); + expectEvent(receipt, 'CustomReferralUpdated', { + customReferral: new BN('10'), + }); + }); + it('reverts - invalid referral code', async () => { + await expectRevert(this.genericAave.setReferralCode(new BN('0'), { from: guardian }), 'invalid referral code'); + }); + }); + + describe('harvestTrigger', () => { + it('success', async () => { + expect(await this.genericAave.harvestTrigger()).to.be.equal(true); + }); + it('success - returns false when weird conditions', async () => { + await this.aaveContract.setUnstakeWindowAndStakers(new BN('0'), new BN('1')); + expect(await this.genericAave.harvestTrigger()).to.be.equal(false); + await this.aaveContract.setUnstakeWindowAndStakers(new BN('0'), MAX_UINT256); + expect(await this.genericAave.harvestTrigger()).to.be.equal(false); + await this.aaveContract.setUnstakeWindowAndStakers(MAX_UINT256, new BN('0')); + }); + }); + + describe('apr & weightedApr - with collateral', () => { + it('success - with no incentives', async () => { + await this.aaveContract.setCurrentLiquidityRate(BASE.mul(new BN('1000000000'))); + expect(await this.genericAave.apr()).to.be.bignumber.equal(BASE); + }); + it('success - with available liquidity and incentives', async () => { + await this.aaveContract.setDistributionEnd(MAX_UINT256); + await this.protocolDataProvider.setAvailableLiquidity(BASE); + // Emissions per second is 10, emissions in want is 100, seconds in year are 31536000 -> 3 153 600 000 + // 3 153 600 000 * 9.5 / 10 + expect(await this.genericAave.apr()).to.be.bignumber.equal( + BASE.add(new BN('3153600000').mul(new BN('95')).div(new BN('100'))), + ); + }); + it('success - with null emissions per second', async () => { + await this.aaveContract.setEmissionsPerSecond(new BN('0')); + expect(await this.genericAave.apr()).to.be.bignumber.equal(BASE); + await this.aaveContract.setEmissionsPerSecond(new BN('10')); + }); + }); + + describe('underlyingBalanceStored', () => { + it('success', async () => { + expect(await this.genericAave.underlyingBalanceStored()).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('withdraw', () => { + it('success - more than total', async () => { + await this.genericAave.withdraw(ether('2'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('1')); + }); + + it('success - without interaction with Aave', async () => { + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.withdraw(ether('1'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('2')); + }); + + it('success - with withdrawal', async () => { + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.deposit({ from: tester }); + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.withdraw(ether('2'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('4')); + }); + + it('success - with no aave swap', async () => { + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.deposit({ from: tester }); + await this.wBTC.mint(this.genericAave.address, ether('1')); + // Add comp gov reward tokens + await this.aaveContract.mint(this.genericAave.address, ether('1')); + // The withdrawal should not swap the aave -> we should use harvest + await this.genericAave.withdraw(ether('2'), { from: tester }); + expect(await this.aaveContract.balanceOf(this.genericAave.address)).to.be.bignumber.equal(ether('1')); + expect(await this.aaveContract.balanceOf(this.uniswapV3Router.address)).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('6')); + }); + }); + + describe('emergencyWithdraw', () => { + it('success', async () => { + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.genericAave.deposit({ from: tester }); + await this.genericAave.emergencyWithdraw(ether('1'), { from: guardian }); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('harvest - with rewards', () => { + it('init', async () => { + await this.aaveContract.mint(this.genericAave.address, ether('1')); + await this.wBTC.mint(this.genericAave.address, ether('1')); + await this.aaveContract.setRewardsBalance(ether('1')); + }); + it('success', async () => { + await this.genericAave.harvest(); + }); + }); + describe('harvest - without rewards', () => { + it('init', async () => { + await this.aaveContract.mint(this.genericAave.address, ether('1')); + await this.wBTC.mint(this.genericAave.address, ether('1')); + }); + it('success', async () => { + await this.genericAave.harvest(); + }); + }); + + describe('aprAfterDeposit - with rewards', () => { + it('init', async () => { + expect(await this.genericAave.aprAfterDeposit(new BN('1'))).to.be.bignumber.equal( + ether('0.04') + .div(new BN('1000000000')) + .add(new BN('3153600000').mul(new BN('95')).div(new BN('100'))) + .sub(new BN('1')), + ); + }); + }); +}); diff --git a/test/genericLender/GenericCompound.test.js b/test/genericLender/GenericCompound.test.js new file mode 100644 index 0000000..312cd94 --- /dev/null +++ b/test/genericLender/GenericCompound.test.js @@ -0,0 +1,323 @@ +require('@openzeppelin/test-helpers/src/setup'); +const { BN } = require('@openzeppelin/test-helpers/src/setup'); +const { + // utils + BASE, + ether, + expectRevert, + expect, + expectApprox, + BASE_ORACLE, + MockOracle, + // functions + initAngle, + initCollateral, + initStrategy, +} = require('../helpers'); + +// Start test block +contract('GenericCompound', accounts => { + const [governor, guardian, user, tester] = accounts; + before(async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + this.oracleETHWant = await MockOracle.new(BASE_ORACLE, new BN('18')); + + [ + this.comp, + this.compound, + this.uniswapRouter, + this.uniswapPool, + this.genericCompound, + this.strategy, + this.uniswapV2Router, + this.comptroller, + ] = await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + + this.supplySpeed = await this.comptroller.price(); + this.blocksPerYear = new BN('2350000'); + + await this.genericCompound.grantRole(web3.utils.soliditySha3('STRATEGY_ROLE'), tester, { from: governor }); + this.guardianRole = web3.utils.soliditySha3('GUARDIAN_ROLE'); + this.guardianError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.guardianRole}`; + this.strategyRole = web3.utils.soliditySha3('STRATEGY_ROLE'); + this.strategyError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.strategyRole}`; + }); + + describe('Initialization', () => { + describe('Parameters', () => { + it('uniswapV3Router', async () => { + expect(await this.genericCompound.uniswapV3Router()).to.be.equal(this.uniswapRouter.address); + }); + it('uniswapV2Router', async () => { + expect(await this.genericCompound.uniswapV2Router()).to.be.equal(this.uniswapV2Router.address); + }); + it('comp', async () => { + expect(await this.genericCompound.comp()).to.be.equal(this.comp.address); + }); + it('comptroller', async () => { + expect(await this.genericCompound.comptroller()).to.be.equal(this.comptroller.address); + }); + it('cToken', async () => { + expect(await this.genericCompound.cToken()).to.be.equal(this.compound.address); + }); + it('minCompToSell', async () => { + expect(await this.genericCompound.minCompToSell()).to.be.bignumber.equal(BASE.div(new BN('2'))); + }); + it('path', async () => { + expect(await this.genericCompound.path()).to.be.equal(web3.utils.asciiToHex('0')); + }); + it('lenderName', async () => { + expect(await this.genericCompound.lenderName()).to.be.equal('wBTC'); + }); + it('poolManager', async () => { + expect(await this.genericCompound.poolManager()).to.be.equal(this.managerBTC.address); + }); + it('strategy', async () => { + expect(await this.genericCompound.strategy()).to.be.equal(this.strategy.address); + }); + it('want', async () => { + expect(await this.genericCompound.want()).to.be.equal(this.wBTC.address); + }); + }); + describe('Access Control', () => { + it('deposit - reverts nonStrategy', async () => { + await expectRevert(this.genericCompound.deposit({ from: user }), this.strategyError); + }); + it('withdraw - reverts nonStrategy', async () => { + await expectRevert(this.genericCompound.withdraw(new BN('1'), { from: user }), this.strategyError); + }); + it('withdrawAll - reverts nonStrategy', async () => { + await expectRevert(this.genericCompound.withdrawAll({ from: user }), this.strategyError); + }); + it('setPath - reverts nonGuardian', async () => { + await expectRevert( + this.genericCompound.setPath(web3.utils.asciiToHex('0'), { from: user }), + this.guardianError, + ); + }); + it('emergencyWithdraw - reverts nonGuardian', async () => { + await expectRevert(this.genericCompound.emergencyWithdraw(new BN('1'), { from: user }), this.guardianError); + }); + it('sweep - reverts nonGuardian', async () => { + await expectRevert.unspecified(this.genericCompound.sweep(this.comp.address, user, { from: user })); + }); + }); + }); + + describe('sweep', () => { + it('reverts - protected token', async () => { + await this.ANGLE.mint(this.genericCompound.address, ether('1')); + await expectRevert(this.genericCompound.sweep(this.comp.address, user, { from: governor }), '93'); + }); + + it('success - balance updated', async () => { + await this.genericCompound.sweep(this.ANGLE.address, user, { from: governor }); + expect(await this.ANGLE.balanceOf(user)).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('deposit', () => { + it('success', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.compound.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('1')); + }); + + it('success - failure of compound catch', async () => { + await expectRevert(this.genericCompound.deposit({ from: tester }), 'mint fail'); + }); + }); + + describe('withdraw', () => { + it('success - more than total', async () => { + await this.genericCompound.withdraw(ether('2'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('1')); + }); + + it('success - without interaction with compound', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.withdraw(ether('1'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('2')); + }); + + it('success - with withdrawal', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.withdraw(ether('2'), { from: tester }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('4')); + }); + + it('success - with comp swap', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + await this.wBTC.mint(this.genericCompound.address, ether('1')); + // Add comp gov reward tokens + await this.comp.mint(this.genericCompound.address, ether('1')); + // The withdrawal should swap the comp + await this.genericCompound.withdraw(ether('2'), { from: tester }); + expect(await this.comp.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.comp.balanceOf(this.uniswapRouter.address)).to.be.bignumber.equal(ether('1')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('7')); + }); + }); + + describe('emergencyWithdraw', () => { + it('success', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + await this.genericCompound.emergencyWithdraw(ether('1'), { from: guardian }); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('withdrawAll', () => { + it('init', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + await this.wBTC.mint(this.genericCompound.address, ether('1')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('2')); + }); + + it('success - success balances updated', async () => { + await this.genericCompound.withdrawAll({ from: tester }); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('9')); + }); + }); + + describe('underlyingBalanceStored', () => { + it('success - without cToken', async () => { + expect(await this.genericCompound.underlyingBalanceStored()).to.be.bignumber.equal(ether('0')); + }); + + it('success - with cToken', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + expect(await this.genericCompound.underlyingBalanceStored()).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('apr', () => { + it('success', async () => { + const cTokenSupply = await this.compound.totalSupply(); + const exchangeRate = await this.compound.exchangeRateStored(); + const supplyInWant = cTokenSupply.mul(exchangeRate).div(BASE); + + const compInWant = this.supplySpeed.mul(new BN('10')); + const incentivesRate = compInWant + .mul(this.blocksPerYear) + .mul(BASE) + .div(supplyInWant) + .mul(new BN(95)) + .div(new BN('100')); + expectApprox(await this.genericCompound.apr(), ether('0.04').add(incentivesRate)); + }); + }); + + describe('aprAfterDeposit', () => { + it('success', async () => { + const cTokenSupply = await this.compound.totalSupply(); + const exchangeRate = await this.compound.exchangeRateStored(); + const supplyInWant = cTokenSupply.mul(exchangeRate).div(BASE).add(ether('1')); + + const compInWant = this.supplySpeed.mul(new BN('10')); + const incentivesRate = compInWant + .mul(this.blocksPerYear) + .mul(BASE) + .div(supplyInWant) + .mul(new BN(95)) + .div(new BN('100')); + expectApprox(await this.genericCompound.aprAfterDeposit(ether('1')), ether('0.04').add(incentivesRate)); + }); + }); + + describe('weightedApr', () => { + it('success', async () => { + await this.wBTC.mint(this.genericCompound.address, ether('1')); + await this.genericCompound.deposit({ from: tester }); + const cTokenSupply = await this.compound.totalSupply(); + const exchangeRate = await this.compound.exchangeRateStored(); + const supplyInWant = cTokenSupply.mul(exchangeRate).div(BASE); + + const compInWant = this.supplySpeed.mul(new BN('10')); + const incentivesRate = compInWant + .mul(this.blocksPerYear) + .mul(BASE) + .div(supplyInWant) + .mul(new BN(95)) + .div(new BN('100')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('2')); + expectApprox(await this.genericCompound.weightedApr(), ether('0.04').add(incentivesRate).mul(ether('2'))); + }); + }); + + describe('hasAssets', () => { + it('success - with assets', async () => { + expect(await this.genericCompound.hasAssets()).to.be.equal(true); + }); + + it('success - without assets', async () => { + await this.genericCompound.withdrawAll({ from: tester }); + expect(await this.genericCompound.hasAssets()).to.be.equal(false); + }); + }); + + describe('setPath', () => { + it('success - path changed', async () => { + this.path = web3.utils.soliditySha3('GUARDIAN_ROLE'); + await this.genericCompound.setPath(this.path, { from: governor }); + expect(await this.genericCompound.path()).to.be.equal(this.path); + }); + }); + describe('apr - with null supply speed', () => { + it('success', async () => { + await this.comptroller.setPrice(new BN('0')); + const supplyRate = await this.compound.supplyRatePerBlock(); + const receipt = await this.genericCompound.apr(); + expect(receipt).to.be.bignumber.equal(supplyRate.mul(new BN('2350000'))); + }); + }); + + describe('withdraw - other branches', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + [ + this.comp, + this.compound, + this.uniswapRouter, + this.uniswapPool, + this.genericCompound, + this.strategy, + this.uniswapV2Router, + this.comptroller, + ] = await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + await this.genericCompound.grantRole(web3.utils.soliditySha3('STRATEGY_ROLE'), tester, { from: governor }); + }); + it('success - null liquidity', async () => { + // Liquidity + await this.compound.mint(this.genericCompound.address, ether('3')); + await this.genericCompound.withdraw(ether('3'), { from: tester }); + }); + it('success - toWithdraw > Liquidity', async () => { + await this.wBTC.mint(this.compound.address, ether('2')); + await this.genericCompound.withdraw(ether('3'), { from: tester }); + }); + }); +}); diff --git a/test/helpers.js b/test/helpers.js new file mode 100644 index 0000000..f3f7965 --- /dev/null +++ b/test/helpers.js @@ -0,0 +1,501 @@ +const { ZERO_ADDRESS, MAX_UINT256 } = require('@openzeppelin/test-helpers/src/constants'); +const { BN, ether, expectEvent, expectRevert, balance, time, send } = require('@openzeppelin/test-helpers'); +const { utils } = require('ethers'); + +function gwei(number) { + return utils.parseUnits(number.toString(), 'gwei'); +} + +const chai = require('chai'); +const { artifacts } = require('hardhat'); +const { expect } = chai; + +// use default BigNumber +chai.use(require('chai-bn')(BN)); + +const BASE = ether('1'); +const BASE_PARAMS = new BN('1000000000'); +const BASE_15 = new BN('1000000000000000'); +const BASE_RATE = new BN(10 ** 2); +const BASE_ORACLE = ether('1'); + +const Core = artifacts.require('Core'); +const AgToken = artifacts.require('AgToken'); +const SanToken = artifacts.require('SanToken'); +const PoolManager = artifacts.require('PoolManager'); +const StableMaster = artifacts.require('StableMasterFront'); +const PerpetualManager = artifacts.require('PerpetualManagerFront'); +const FeeManager = artifacts.require('FeeManager'); +const BondingCurve = artifacts.require('BondingCurve'); +const CollateralSettlerVeANGLE = artifacts.require('CollateralSettlerVeANGLE'); +const Orchestrator = artifacts.require('Orchestrator'); +const OrchestratorOwnable = artifacts.require('OrchestratorOwnable'); +const AngleDistributor = artifacts.require('AngleDistributor'); + +const GenericCompound = artifacts.require('GenericCompound'); +const GenericAave = artifacts.require('GenericAave'); +const Strategy = artifacts.require('Strategy'); +const StrategyStETHAcc = artifacts.require('StrategyStETHAcc'); + +const MockOracle = artifacts.require('MockOracle'); +const MockGaugeController = artifacts.require('MockGaugeController'); +const MockLiquidityGauge = artifacts.require('MockLiquidityGauge'); +const MockCore = artifacts.require('MockCore'); +const MockOracleMath = artifacts.require('MockOracleMath'); +const MockPath = artifacts.require('ComputePath'); +const MockPathComplex = artifacts.require('ComputePathComplex'); +const OracleMulti = artifacts.require('OracleMulti'); +const OracleDAI = artifacts.require('OracleDAI'); +const OracleClSingle = artifacts.require('OracleChainlinkSingle'); +const MockChainlinkOracle = artifacts.require('MockChainlinkOracle'); +const MockChainlinkOracleNullRoundData = artifacts.require('MockChainlinkOracleNullRoundData'); +const MockUniswapV3Pool = artifacts.require('MockUniswapV3Pool'); +const MockERC721Holder = artifacts.require('ERC721Holder'); +const MockERC721HolderWrongReason = artifacts.require('ERC721HolderWrongReason'); + +const MockToken = artifacts.require('MockToken'); +const MockWETH = artifacts.require('MockWETH'); +const MockStETH = artifacts.require('MockStETH'); +const MockCurveStETHETH = artifacts.require('MockCurveStETHETH'); +const MockANGLE = artifacts.require('MockANGLE'); +const MockBot = artifacts.require('MockBot'); + +const MockStrategy = artifacts.require('MockStrategy'); +const MockCompound = artifacts.require('MockCompound'); +const MockAave = artifacts.require('MockAave'); +const MockProtocolDataProvider = artifacts.require('MockProtocolDataProvider'); +const MockComptroller = artifacts.require('MockComptroller'); +const MockFeeDistributor = artifacts.require('MockFeeDistributor'); +const MockUniswapV3Router = artifacts.require('MockUniswapV3Router'); +const MockUniswapV2Router = artifacts.require('MockUniswapV2Router'); + +const SmartWalletWhitelist = artifacts.require('SmartWalletWhitelist'); +const SurplusConverterUniV2Sushi = artifacts.require('SurplusConverterUniV2Sushi'); +const SurplusConverterUniV3 = artifacts.require('SurplusConverterUniV3'); +const SurplusConverterSanTokens = artifacts.require('SurplusConverterSanTokens'); + +const AngleStakingRewards = artifacts.require('StakingRewards'); +const RewardsDistributor = artifacts.require('RewardsDistributor'); +const PoolAddress = artifacts.require('PoolAddress'); + +const MAX_MINT_AMOUNT = new BN(2).pow(new BN(256)).sub(new BN(1)); + +async function initAngle(governor, guardian) { + const core = await Core.new(governor, guardian); + + const ANGLE = await MockANGLE.new('ANGLE', 'ANGLE'); + const stableMaster = await StableMaster.new(); + await stableMaster.initialize(core.address); + const agToken = await AgToken.new(); + await agToken.initialize('agEUR', 'agEUR', stableMaster.address); + await core.deployStableMaster(agToken.address, { from: governor }); + + return [core, ANGLE, stableMaster, agToken]; +} + +async function initCollateral(name, stableMaster, ANGLE, governor, collatBase = new BN('18'), setFees = true) { + const token = await MockToken.new(name, name, collatBase); + const oracle = await MockOracle.new(BASE_ORACLE, collatBase); + const manager = await PoolManager.new(); + + await manager.initialize(token.address, stableMaster.address); + const sanToken = await SanToken.new(); + await sanToken.initialize('san' + name, 'san' + name, manager.address); + const perpetualManager = await PerpetualManager.new(); + await perpetualManager.initialize(manager.address, ANGLE.address); + const feeManager = await FeeManager.new(manager.address); + + await stableMaster.deployCollateral( + manager.address, + perpetualManager.address, + feeManager.address, + oracle.address, + sanToken.address, + { from: governor }, + ); + + if (setFees) { + // For test purpose + const xFeeMint = [new BN('0'), gwei('1')]; + const yFeeMint = [gwei('0.1'), gwei('0.1')]; + await stableMaster.setUserFees(manager.address, xFeeMint, yFeeMint, 1, { from: governor }); + + const xFeeBurn = [ether('0'), gwei('1')]; + const yFeeBurn = [gwei('0.1'), gwei('0.1')]; + await stableMaster.setUserFees(manager.address, xFeeBurn, yFeeBurn, 0, { from: governor }); + + const xHAFeesDeposit = [gwei('0.1'), gwei('0.4'), gwei('0.7')]; + const yHAFeesDeposit = [gwei('0.01'), gwei('0.01'), gwei('0.01')]; + await perpetualManager.setHAFees(xHAFeesDeposit, yHAFeesDeposit, 1, { from: governor }); + + const xHAFeesWithdraw = [gwei('0.1'), gwei('0.4'), gwei('0.7')]; + const yHAFeesWithdraw = [gwei('0.01'), gwei('0.01'), gwei('0.01')]; + await perpetualManager.setHAFees(xHAFeesWithdraw, yHAFeesWithdraw, 0, { from: governor }); + + const xSlippage = [gwei('1'), gwei('1.5')]; + const ySlippage = [gwei('1'), gwei('0')]; + const xSlippageFee = [gwei('1'), gwei('1.5')]; + const ySlippageFee = [gwei('1'), gwei('0')]; + await feeManager.setFees(xSlippage, ySlippage, 3, { from: governor }); + await feeManager.setFees(xSlippageFee, ySlippageFee, 0, { from: governor }); + } else { + const xFeeMint = [gwei('0'), gwei('0.4'), gwei('0.7'), gwei('1')]; + const yFeeMint = [gwei('0.002'), gwei('0.005'), gwei('0.025'), gwei('0.08')]; + await stableMaster.setUserFees(manager.address, xFeeMint, yFeeMint, 1, { from: governor }); + + const xFeeBurn = [gwei('0'), gwei('0.4'), gwei('0.7'), gwei('1')]; + const yFeeBurn = [gwei('0.015'), gwei('0.005'), gwei('0.003'), gwei('0.002')]; + await stableMaster.setUserFees(manager.address, xFeeBurn, yFeeBurn, 0, { from: governor }); + + const xHAFeesDeposit = [gwei('0'), gwei('0.4'), gwei('0.7'), gwei('1')]; + const yHAFeesDeposit = [gwei('0.03'), gwei('0.01'), gwei('0.005'), gwei('0.002')]; + await perpetualManager.setHAFees(xHAFeesDeposit, yHAFeesDeposit, 1, { from: governor }); + + const xHAFeesWithdraw = [gwei('0'), gwei('0.4'), gwei('0.7'), gwei('1')]; + const yHAFeesWithdraw = [gwei('0.002'), gwei('0.01'), gwei('0.02'), gwei('0.06')]; + await perpetualManager.setHAFees(xHAFeesWithdraw, yHAFeesWithdraw, 0, { from: governor }); + + const xSlippage = [gwei('0.5'), gwei('1'), gwei('1.2'), gwei('1.5')]; + const ySlippage = [gwei('0.5'), gwei('0.2'), gwei('0.1'), gwei('0')]; + const xSlippageFee = [gwei('0.5'), gwei('1'), gwei('1.2'), gwei('1.5')]; + const ySlippageFee = [gwei('0.75'), gwei('0.5'), gwei('0.15'), gwei('0')]; + + await feeManager.setFees(xSlippage, ySlippage, 3, { from: governor }); + await feeManager.setFees(xSlippageFee, ySlippageFee, 0, { from: governor }); + } + const xBonusMalusMint = [gwei('0.5'), gwei('1')]; + const yBonusMalusMint = [gwei('0.8'), gwei('1')]; + const xBonusMalusBurn = [gwei('0'), gwei('0.5'), gwei('1'), gwei('1.3'), gwei('1.5')]; + const yBonusMalusBurn = [gwei('10'), gwei('4'), gwei('1.5'), gwei('1'), gwei('1')]; + await feeManager.setFees(xBonusMalusMint, yBonusMalusMint, 1, { from: governor }); + await feeManager.setFees(xBonusMalusBurn, yBonusMalusBurn, 2, { from: governor }); + await feeManager.setHAFees(gwei('1'), gwei('1'), { from: governor }); + + await stableMaster.setIncentivesForSLPs(gwei('0.5'), gwei('0.5'), manager.address, { from: governor }); + await stableMaster.setCapOnStableAndMaxInterests(MAX_UINT256, new BN('10').pow(collatBase), manager.address, { + from: governor, + }); + + // Limit HA hedge should always be set before the target HA hedge + await perpetualManager.setTargetAndLimitHAHedge(gwei('0.9'), gwei('0.95'), { from: governor }); + await perpetualManager.setBoundsPerpetual(gwei('3'), gwei('0.0625'), { from: governor }); + await perpetualManager.setKeeperFeesLiquidationRatio(gwei('0.2'), { from: governor }); + await perpetualManager.setKeeperFeesCap(ether('100'), ether('100'), { from: governor }); + const xKeeperFeesClosing = [gwei('0.25'), gwei('0.5'), gwei('1')]; + const yKeeperFeesClosing = [gwei('0.1'), gwei('0.6'), gwei('0.1')]; + await perpetualManager.setKeeperFeesClosing(xKeeperFeesClosing, yKeeperFeesClosing, { from: governor }); + + await feeManager.updateUsersSLP(); + await feeManager.updateHA(); + + await stableMaster.unpause(web3.utils.soliditySha3('STABLE'), manager.address, { from: governor }); + await stableMaster.unpause(web3.utils.soliditySha3('SLP'), manager.address, { from: governor }); + await perpetualManager.unpause({ from: governor }); + + return [token, oracle, manager, sanToken, perpetualManager, feeManager]; +} + +async function initWETH(stableMaster, ANGLE, governor, guardian, collatBase = new BN('18')) { + const token = await MockWETH.new('WETH', 'WETH', collatBase); + const oracle = await MockOracle.new(BASE_ORACLE, collatBase); + const manager = await PoolManager.new(); + + await manager.initialize(token.address, stableMaster.address); + const sanToken = await SanToken.new(); + await sanToken.initialize('sanWETH', 'sanWETH', manager.address); + const perpetualManager = await PerpetualManager.new(); + await perpetualManager.initialize(manager.address, ANGLE.address); + const feeManager = await FeeManager.new(manager.address); + + await stableMaster.deployCollateral( + manager.address, + perpetualManager.address, + feeManager.address, + oracle.address, + sanToken.address, + { from: governor }, + ); + const xFeeMint = [new BN('0'), gwei('1')]; + const yFeeMint = [gwei('0.1'), gwei('0.1')]; + await stableMaster.setUserFees(manager.address, xFeeMint, yFeeMint, 1, { from: governor }); + + const xFeeBurn = [ether('0'), gwei('1')]; + const yFeeBurn = [gwei('0.1'), gwei('0.1')]; + await stableMaster.setUserFees(manager.address, xFeeBurn, yFeeBurn, 0, { from: governor }); + + const xHAFeesDeposit = [gwei('0.1'), gwei('0.4'), gwei('0.7')]; + const yHAFeesDeposit = [gwei('0.01'), gwei('0.01'), gwei('0.01')]; + await perpetualManager.setHAFees(xHAFeesDeposit, yHAFeesDeposit, 1, { from: governor }); + + const xHAFeesWithdraw = [gwei('0.1'), gwei('0.4'), gwei('0.7')]; + const yHAFeesWithdraw = [gwei('0.01'), gwei('0.01'), gwei('0.01')]; + await perpetualManager.setHAFees(xHAFeesWithdraw, yHAFeesWithdraw, 0, { from: governor }); + + const xSlippage = [gwei('1'), gwei('1.5')]; + const ySlippage = [gwei('1'), gwei('0')]; + const xSlippageFee = [gwei('1'), gwei('1.5')]; + const ySlippageFee = [gwei('1'), gwei('0')]; + await feeManager.setFees(xSlippage, ySlippage, 3, { from: governor }); + await feeManager.setFees(xSlippageFee, ySlippageFee, 0, { from: governor }); + const xBonusMalusMint = [gwei('0.5'), gwei('1')]; + const yBonusMalusMint = [gwei('0.8'), gwei('1')]; + const xBonusMalusBurn = [gwei('0'), gwei('0.5'), gwei('1'), gwei('1.3'), gwei('1.5')]; + const yBonusMalusBurn = [gwei('10'), gwei('4'), gwei('1.5'), gwei('1'), gwei('1')]; + await feeManager.setFees(xBonusMalusMint, yBonusMalusMint, 1, { from: governor }); + await feeManager.setFees(xBonusMalusBurn, yBonusMalusBurn, 2, { from: governor }); + await feeManager.setHAFees(gwei('1'), gwei('1'), { from: governor }); + + await stableMaster.setIncentivesForSLPs(gwei('0.5'), gwei('0.5'), manager.address, { from: governor }); + await stableMaster.setCapOnStableAndMaxInterests(MAX_UINT256, new BN('10').pow(collatBase), manager.address, { + from: governor, + }); + + // Limit HA hedge should always be set before the target HA hedge + await perpetualManager.setTargetAndLimitHAHedge(gwei('0.9'), gwei('0.95'), { from: governor }); + await perpetualManager.setBoundsPerpetual(gwei('3'), gwei('0.0625'), { from: governor }); + await perpetualManager.setKeeperFeesLiquidationRatio(gwei('0.2'), { from: governor }); + await perpetualManager.setKeeperFeesCap(ether('100'), ether('100'), { from: governor }); + const xKeeperFeesClosing = [gwei('0.25'), gwei('0.5'), gwei('1')]; + const yKeeperFeesClosing = [gwei('0.1'), gwei('0.6'), gwei('0.1')]; + await perpetualManager.setKeeperFeesClosing(xKeeperFeesClosing, yKeeperFeesClosing, { from: governor }); + + await feeManager.updateUsersSLP(); + await feeManager.updateHA(); + + await stableMaster.unpause(web3.utils.soliditySha3('STABLE'), manager.address, { from: governor }); + await stableMaster.unpause(web3.utils.soliditySha3('SLP'), manager.address, { from: governor }); + await perpetualManager.unpause({ from: governor }); + + const stETH = await MockStETH.new('stETH', 'stETH', collatBase); + const curve = await MockCurveStETHETH.new(stETH.address); + + const strategy = await StrategyStETHAcc.new( + manager.address, + ANGLE.address, + [governor], + guardian, + curve.address, + token.address, + stETH.address, + ); + + await manager.addStrategy(strategy.address, gwei('0.8'), { from: governor }); + + return [token, oracle, manager, sanToken, perpetualManager, feeManager, stETH, curve, strategy]; +} + +async function initStrategy(name, token, manager, ANGLE, oracle, governor, guardian) { + const comp = await MockToken.new('COMP', 'COMP', 18); + const weth = await MockToken.new('WETH', 'WETH', 18); + const compound = await MockCompound.new('c' + name, 'c' + name, token.address); + + const uniswapPool = await initMockUniPoolDeterministic(weth.address, token.address); + const uniswapRooter = await MockUniswapV3Router.new(comp.address, token.address); + const uniswapV2Router = await MockUniswapV2Router.new(new BN('10')); + // Price obtained from a Compound price feed + const comptroller = await MockComptroller.new(new BN('1462500000000000')); + + const strategy = await Strategy.new(manager.address, ANGLE.address, [governor], guardian); + strategy.setWithdrawalThreshold(new BN('100000000000000')); + + const genericCompound = await GenericCompound.new( + strategy.address, + name, + uniswapRooter.address, + uniswapV2Router.address, + comptroller.address, + comp.address, + web3.utils.asciiToHex('0'), + compound.address, + [governor], + guardian, + ); + + await strategy.addLender(genericCompound.address, { from: governor }); + + await manager.addStrategy(strategy.address, gwei('0.8'), { from: governor }); + + return [comp, compound, uniswapRooter, uniswapPool, genericCompound, strategy, uniswapV2Router, comptroller]; +} + +async function getInfoUniPool(factory, inERC20, outERC20, fee) { + const poolAddress = await PoolAddress.new(); + let isMultiplied; + const addressPool = await poolAddress.computeAddress(factory, await poolAddress.getPoolKey(inERC20, outERC20, fee)); + if (inERC20 < outERC20) isMultiplied = 1; + else isMultiplied = 0; + + return [addressPool, isMultiplied]; +} + +async function initMockClOracle(decimals, desc) { + const oracle = await MockChainlinkOracle.new(); + await oracle.setDecimals(decimals); + await oracle.setDescritpion(desc); + await oracle.setLatestAnswer(new BN(10).pow(decimals), await time.latest()); + + return oracle; +} + +async function initMockUniPool(tokenIn, tokenOut) { + const uniPool = await MockUniswapV3Pool.new(tokenIn, tokenOut); + let rdnNumber; + const max = 1000000; + const min = 100; + for (let i = 0; i < 50; i++) { + rdnNumber = Math.floor(Math.random() * (max - min + 1)) + min; + await uniPool.updateNextTick(rdnNumber); + } + + return uniPool; +} + +async function initMockUniPooLPartialRandom(tokenIn, tokenOut) { + const uniPool = await MockUniswapV3Pool.new(tokenIn, tokenOut); + let rdnNumber; + let cst = 1000; + const max = 100000; + const min = 90000; + for (let i = 0; i < 50; i++) { + rdnNumber = Math.floor(Math.random() * (max - min + 1)) + min; + await uniPool.updateNextTick(cst + rdnNumber); + cst += 100; + } + + return uniPool; +} + +// initialize the ticks such that the price is multiplied by 2 at each block +async function initMockUniPoolDeterministic(tokenIn, tokenOut) { + const uniPool = await MockUniswapV3Pool.new(tokenIn, tokenOut); + let nexTickVal = 0; + await uniPool.updateNextTick(new BN(0)); + for (let i = 1; i < 50; i++) { + nexTickVal += 1; + await uniPool.updateNextTick(new BN(nexTickVal)); + } + + return uniPool; +} + +// Function to watch event +async function getEvent(contract, eventName) { + const events = await contract.getPastEvents(eventName, { fromBlock: 0 }); + for (let i = 0; i < events.length; i++) { + console.log(events[i].args); + } +} + +async function expectApprox(actual, expected) { + const delta = expected.div(new BN('100')); + expect(actual).to.be.bignumber.closeTo(expected, delta); +} + +async function expectApproxDelta(actual, expected, margin) { + const delta = expected.mul(margin).div(new BN('100')); + expect(actual).to.be.bignumber.closeTo(expected, delta); +} + +const FEE_SIZE = 3; + +function encodePath(path, fees) { + if (path.length !== fees.length + 1) { + throw new Error('path/fee lengths do not match'); + } + + let encoded = '0x'; + for (let i = 0; i < fees.length; i++) { + // 20 byte encoding of the address + encoded += path[i].slice(2); + // 3 byte encoding of the fee + encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0'); + } + // encode the final token + encoded += path[path.length - 1].slice(2); + + return encoded.toLowerCase(); +} + +module.exports = { + // utils, + ZERO_ADDRESS, + MAX_UINT256, + web3, + BN, + balance, + ether, + gwei, + encodePath, + expectEvent, + expectRevert, + expectApprox, + expectApproxDelta, + time, + send, + expect, + BASE, + BASE_PARAMS, + BASE_RATE, + BASE_15, + BASE_ORACLE, + MAX_MINT_AMOUNT, + // contracts + Core, + AgToken, + SanToken, + PoolManager, + StableMaster, + Strategy, + PerpetualManager, + AngleStakingRewards, + RewardsDistributor, + AngleDistributor, + BondingCurve, + FeeManager, + CollateralSettlerVeANGLE, + StrategyStETHAcc, + PoolAddress, + SurplusConverterUniV2Sushi, + SurplusConverterUniV3, + SurplusConverterSanTokens, + // mock contracts + MockOracle, + MockOracleMath, + MockERC721Holder, + MockERC721HolderWrongReason, + OracleDAI, + OracleMulti, + OracleClSingle, + Orchestrator, + OrchestratorOwnable, + MockChainlinkOracle, + MockLiquidityGauge, + MockGaugeController, + MockChainlinkOracleNullRoundData, + MockUniswapV3Pool, + GenericAave, + MockUniswapV2Router, + MockUniswapV3Router, + MockFeeDistributor, + MockToken, + MockPath, + MockPathComplex, + MockBot, + MockCore, + MockStrategy, + MockCompound, + MockAave, + MockProtocolDataProvider, + SmartWalletWhitelist, + // functions + getEvent, + initAngle, + initCollateral, + initWETH, + initStrategy, + initMockClOracle, + initMockUniPool, + initMockUniPoolDeterministic, + initMockUniPooLPartialRandom, + getInfoUniPool, +}; diff --git a/test/poolManager/PoolManager.test.js b/test/poolManager/PoolManager.test.js new file mode 100644 index 0000000..00f0a72 --- /dev/null +++ b/test/poolManager/PoolManager.test.js @@ -0,0 +1,510 @@ +const { MAX_UINT256 } = require('@openzeppelin/test-helpers/src/constants'); +const { + // utils + web3, + BN, + expectEvent, + expectRevert, + expect, + // params + BASE, + BASE_PARAMS, + // functions + initAngle, + initCollateral, + MockStrategy, + PoolManager, + ZERO_ADDRESS, +} = require('../helpers'); + +// Start test block +contract('PoolManager', accounts => { + const [governor, guardian, user, user2, minter] = accounts; + + describe('PoolManager', () => { + before(async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC, this.feeManager] = + await initCollateral('wBTC', this.stableMaster, this.ANGLE, governor); + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI, this.feeManagerDAI] = + await initCollateral('DAI', this.stableMaster, this.ANGLE, governor, new BN('18')); + this.HA = web3.utils.soliditySha3('HA'); + this.SLP = web3.utils.soliditySha3('SLP'); + this.STABLE_HOLDER = web3.utils.soliditySha3('STABLE_HOLDER'); + + await this.wBTC.mint(user, new BN(1000).mul(BASE)); + await this.wBTC.mint(user2, new BN(1000).mul(BASE)); + this.governorRole = web3.utils.soliditySha3('GOVERNOR_ROLE'); + this.guardianRole = web3.utils.soliditySha3('GUARDIAN_ROLE'); + this.governorError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.governorRole}`; + this.guardianError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.guardianRole}`; + this.stableMasterRole = web3.utils.soliditySha3('STABLEMASTER_ROLE'); + this.feeManagerRole = web3.utils.soliditySha3('FEEMANAGER_ROLE'); + this.stableMasterError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.stableMasterRole}`; + this.feeManagerError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.feeManagerRole}`; + this.strategyRole = web3.utils.soliditySha3('STRATEGY_ROLE'); + this.strategyError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.strategyRole}`; + }); + describe('Initialization', () => { + it('token', async () => { + expect(await this.managerBTC.token()).to.be.equal(this.wBTC.address); + }); + it('perpetual manager', async () => { + expect(await this.managerBTC.perpetualManager()).to.be.equal(this.perpetualManagerBTC.address); + }); + it('stableMaster', async () => { + expect(await this.managerBTC.stableMaster()).to.be.equal(this.stableMaster.address); + }); + it('keeper', async () => { + expect(await this.managerBTC.feeManager()).to.be.equal(this.feeManager.address); + }); + it('totalDebt', async () => { + expect(await this.managerBTC.totalDebt()).to.be.bignumber.equal(new BN('0')); + }); + it('debtRatio', async () => { + expect(await this.managerBTC.debtRatio()).to.be.bignumber.equal(new BN('0')); + }); + it('interestsAccumulated', async () => { + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + }); + it('interestsForSurplus', async () => { + expect(await this.managerBTC.interestsForSurplus()).to.be.bignumber.equal(new BN('0')); + }); + it('surplusConverter', async () => { + expect(await this.managerBTC.surplusConverter()).to.be.equal(ZERO_ADDRESS); + }); + it('constructor reverts - zero token address', async () => { + const manager = await PoolManager.new(); + await expectRevert(manager.initialize(ZERO_ADDRESS, this.stableMaster.address), '0'); + }); + it('constructor reverts - zero stableMaster address', async () => { + const manager = await PoolManager.new(); + await expectRevert(manager.initialize(this.wBTC.address, ZERO_ADDRESS), '0'); + }); + }); + + describe('AccessControl', () => { + it('governor & guardian', async () => { + expect(await this.managerBTC.hasRole(web3.utils.soliditySha3('GOVERNOR_ROLE'), governor)).to.be.equal(true); + expect(await this.managerBTC.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), guardian)).to.be.equal(true); + expect(await this.managerBTC.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), governor)).to.be.equal(true); + }); + it('StableMaster', async () => { + expect( + await this.managerBTC.hasRole(web3.utils.soliditySha3('STABLEMASTER_ROLE'), this.stableMaster.address), + ).to.be.equal(true); + }); + it('deployCollateral - reverts nonStableMaster', async () => { + await expectRevert( + this.managerBTC.deployCollateral( + [governor], + governor, + this.perpetualManagerBTC.address, + this.feeManager.address, + this.oracleBTC.address, + { from: user }, + ), + this.stableMasterError, + ); + }); + + it('grantRole - reverts nonStableMaster', async () => { + await expectRevert.unspecified( + this.managerBTC.grantRole(web3.utils.soliditySha3('STRATEGY_ROLE'), user, { from: user }), + ); + }); + + it('addGovernor - reverts nonStableMaster', async () => { + await expectRevert(this.managerBTC.addGovernor(governor, { from: user }), this.stableMasterError); + }); + it('removeGovernor - reverts nonStableMaster', async () => { + await expectRevert(this.managerBTC.removeGovernor(governor, { from: user }), this.stableMasterError); + }); + it('setGuardian - reverts nonStableMaster', async () => { + await expectRevert(this.managerBTC.setGuardian(governor, guardian, { from: user }), this.stableMasterError); + }); + it('revokeGuardian - reverts nonStableMaster', async () => { + await expectRevert(this.managerBTC.revokeGuardian(guardian, { from: user }), this.stableMasterError); + }); + it('setFeeManager - reverts nonStableMaster', async () => { + await expectRevert( + this.managerBTC.setFeeManager(this.feeManager.address, { from: user }), + this.stableMasterError, + ); + }); + it('addStrategy - reverts nonGovernor', async () => { + await expectRevert(this.managerBTC.addStrategy(user, BASE, { from: user }), this.governorError); + }); + it('report - reverts nonStrategy', async () => { + await expectRevert(this.managerBTC.report(BASE, BASE, BASE, { from: user }), this.strategyError); + }); + it('recoverERC20 - reverts nonGovernor', async () => { + await expectRevert( + this.managerBTC.recoverERC20(this.wBTC.address, user, BASE, { from: user }), + this.governorError, + ); + }); + it('updateStrategyDebtRatio - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.updateStrategyDebtRatio(user, BASE, { from: user }), this.guardianError); + }); + it('setStrategyEmergencyExit - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.setStrategyEmergencyExit(user, { from: user }), this.guardianError); + }); + it('revokeStrategy - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.revokeStrategy(user, { from: user }), this.guardianError); + }); + it('withdrawFromStrategy - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.withdrawFromStrategy(user, BASE, { from: user }), this.guardianError); + }); + it('setInterestsForSurplus - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.setInterestsForSurplus(new BN('1'), { from: user }), this.guardianError); + }); + it('setSurplusConverter - reverts nonGuardian', async () => { + await expectRevert(this.managerBTC.setSurplusConverter(user, { from: user }), this.guardianError); + }); + }); + + describe('Mock Token', () => { + describe('mint', () => { + it('success - balance updated', async () => { + expect(await this.wBTC.balanceOf(user)).to.be.bignumber.equal(new BN(1000).mul(BASE)); + }); + }); + describe('transfer', () => { + before(async () => { + await this.wBTC.transfer(minter, new BN(100).mul(BASE), { from: user }); + }); + it('success - minter balance updated', async () => { + expect(await this.wBTC.balanceOf(minter)).to.be.bignumber.equal(new BN(100).mul(BASE)); + }); + + it('success - contract balance updated', async () => { + expect(await this.managerBTC.getBalance()).to.be.bignumber.equal(new BN(0)); + }); + }); + }); + + describe('Governance Functions', () => { + describe('setInterestsForSurplus', () => { + it('reverts - too big amount', async () => { + await expectRevert( + this.managerBTC.setInterestsForSurplus(BASE_PARAMS.mul(new BN('2')), { from: governor }), + '4', + ); + }); + it('success - value updated', async () => { + await this.managerBTC.setInterestsForSurplus(new BN('1'), { from: guardian }); + expect(await this.managerBTC.interestsForSurplus()).to.be.bignumber.equal(new BN('1')); + }); + it('success - value reset', async () => { + await this.managerBTC.setInterestsForSurplus(new BN('0'), { from: guardian }); + expect(await this.managerBTC.interestsForSurplus()).to.be.bignumber.equal(new BN('0')); + }); + }); + describe('setSurplusConverter', () => { + it('pushSurplus reverts - zero address', async () => { + await expectRevert(this.managerBTC.pushSurplus(), '0'); + }); + it('success - role granted', async () => { + await this.managerBTC.setSurplusConverter(guardian, { from: guardian }); + expect(await this.managerBTC.surplusConverter()).to.be.equal(guardian); + }); + it('success - role revoked and granted', async () => { + await this.managerBTC.setSurplusConverter(governor, { from: guardian }); + expect(await this.managerBTC.surplusConverter()).to.be.equal(governor); + }); + }); + }); + describe('pushSurplus', () => { + it('success - normal value', async () => { + await this.managerBTC.pushSurplus(); + }); + }); + + describe('recoverERC20 - underlying token', () => { + it('reverts - too big amount', async () => { + await expectRevert( + this.managerBTC.recoverERC20(this.wBTC.address, user, MAX_UINT256, { from: governor }), + '66', + ); + }); + it('success - works fine', async () => { + const balance = await this.managerBTC.getBalance(); + const receipt = await this.managerBTC.recoverERC20(this.wBTC.address, user, balance, { from: governor }); + + expectEvent(receipt, 'Recovered', { + token: this.wBTC.address, + to: user, + amount: balance, + }); + }); + it('success - balance updated', async () => { + expect(await this.managerBTC.getBalance()).to.be.bignumber.equal(new BN('0')); + }); + it('reverts - too much withdrawn compared with user claims', async () => { + await this.wBTC.mint(user, new BN(1000).mul(BASE)); + await this.wBTC.approve(this.stableMaster.address, new BN(1000).mul(BASE), { from: user }); + await this.stableMaster.mint(BASE, user, this.managerBTC.address, new BN('0'), { from: user }); + expect(await this.managerBTC.getBalance()).to.be.bignumber.equal(BASE); + await expectRevert( + this.managerBTC.recoverERC20(this.wBTC.address, user, BASE.sub(new BN('1')), { from: governor }), + '66', + ); + }); + }); + describe('recoverERC20 - other token', () => { + it('success - mint', async () => { + await this.DAI.mint(this.managerBTC.address, new BN('1000').mul(BASE)); + expect(await this.DAI.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(new BN('1000').mul(BASE)); + }); + it('reverts - too big amount', async () => { + await expectRevert.unspecified( + this.managerBTC.recoverERC20(this.DAI.address, user, new BN('10000').mul(BASE), { from: governor }), + ); + }); + it('success - recovered', async () => { + await this.managerBTC.recoverERC20(this.DAI.address, user, new BN('1000').mul(BASE), { from: governor }); + expect(await this.DAI.balanceOf(user)).to.be.bignumber.equal(new BN('1000').mul(BASE)); + }); + }); + describe('addStrategy', () => { + it('success', async () => { + this.strategy = await MockStrategy.new(this.managerBTC.address, this.wBTC.address); + await this.managerBTC.addStrategy(this.strategy.address, BASE_PARAMS.div(new BN('2')), { from: governor }); + this.strategy2 = await MockStrategy.new(this.managerBTC.address, this.wBTC.address); + await this.managerBTC.addStrategy(this.strategy2.address, BASE_PARAMS.div(new BN('4')), { from: governor }); + }); + }); + describe('report', () => { + it('reverts - incorrect freed amount', async () => { + await expectRevert(this.strategy.report(BASE, 0, BASE), '72'); + }); + it('success - correct freed amount', async () => { + await this.strategy.report(0, 0, 0); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(BASE.div(new BN('2'))); + }); + it('success - correct freed amount', async () => { + await this.strategy2.report(0, 0, 0); + expect(await this.wBTC.balanceOf(this.strategy2.address)).to.be.bignumber.equal(BASE.div(new BN('4'))); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(BASE.div(new BN('4'))); + }); + it('success - with no collateral available', async () => { + // There is BASE/4 left in the protocol: to bring the balance to 0, we should burn with 90% fees + // BASE/4*10/9 + await this.stableMaster.burn( + BASE.mul(new BN('100')).div(new BN('360')).add(new BN('1')), + user, + user, + this.managerBTC.address, + new BN('0'), + { from: user }, + ); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(new BN('0')); + await this.strategy.report(0, BASE.div(new BN('3')), 0); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(BASE.div(new BN('2'))); + }); + it('creditAvailable - success', async () => { + expect(await this.strategy2.creditAvailable()).to.be.bignumber.equal(new BN('0')); + }); + + it('withdrawFromStrategy with loss - success', async () => { + const receipt = await this.managerBTC.withdrawFromStrategy(this.strategy.address, BASE.div(new BN('100'))); + expectEvent(receipt, 'StrategyReported', { + loss: new BN('1'), + }); + }); + }); + describe('report - with loss and lockedInterests taken to reimburse the loss', () => { + it('success - loss smaller than lockedInterests', async () => { + await this.wBTC.approve(this.stableMaster.address, new BN(100).mul(BASE), { from: user2 }); + await this.stableMaster.deposit(BASE.div(new BN(100)), user2, this.managerBTC.address, { from: user2 }); + await this.stableMaster.mint(new BN(BASE), user, this.managerBTC.address, new BN('0'), { from: user }); + await this.stableMaster.burn( + BASE.mul(new BN('90')).div(new BN('100')), + user, + user, + this.managerBTC.address, + new BN('0'), + { from: user }, + ); + let colData = await this.stableMaster.collateralMap(this.managerBTC.address); + const lockedInterests = new BN(colData.slpData.lockedInterests); + const prevSanRate = colData.sanRate; + await this.strategy.report(0, lockedInterests.div(new BN(2)), 0); + colData = await this.stableMaster.collateralMap(this.managerBTC.address); + expect(colData.sanRate).to.be.bignumber.equal(prevSanRate); + }); + it('success - loss larger than LockedInterests', async () => { + await this.stableMaster.mint(new BN(BASE), user, this.managerBTC.address, new BN('0'), { from: user }); + await this.stableMaster.burn( + BASE.mul(new BN('90')).div(new BN('100')), + user, + user, + this.managerBTC.address, + new BN('0'), + { from: user }, + ); + let colData = await this.stableMaster.collateralMap(this.managerBTC.address); + const lockedInterests = new BN(colData.slpData.lockedInterests); + const prevSanRate = colData.sanRate; + const sanMint = await this.sanBTC_EUR.totalSupply(); + const loss = lockedInterests.mul(new BN(2)); + await this.strategy.report(0, loss, 0); + colData = await this.stableMaster.collateralMap(this.managerBTC.address); + const newSanRate = prevSanRate.sub(loss.sub(lockedInterests).mul(BASE).div(sanMint)); + expect(colData.sanRate).to.be.bignumber.equal(newSanRate); + }); + it('success - loss needs to pause', async () => { + await this.stableMaster.mint(new BN(BASE), user, this.managerBTC.address, new BN('0'), { from: user }); + await this.stableMaster.burn( + BASE.mul(new BN('90')).div(new BN('100')), + user, + user, + this.managerBTC.address, + new BN('0'), + { from: user }, + ); + let colData = await this.stableMaster.collateralMap(this.managerBTC.address); + const lockedInterests = new BN(colData.slpData.lockedInterests); + const prevSanRate = colData.sanRate; + const sanMint = await this.sanBTC_EUR.totalSupply(); + const loss = sanMint.mul(prevSanRate).div(BASE).add(lockedInterests); + await this.strategy.report(0, loss, 0); + colData = await this.stableMaster.collateralMap(this.managerBTC.address); + expect(colData.sanRate).to.be.bignumber.equal(new BN(1)); + expect(colData.slpData.lockedInterests).to.be.bignumber.equal(new BN('0')); + await expectRevert( + this.stableMaster.deposit(new BN(BASE), user, this.managerBTC.address, { from: user }), + '18', + ); + }); + }); + describe('report - with non null interestsForSurplus', () => { + it('init ', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC, this.feeManager] = + await initCollateral('wBTC', this.stableMaster, this.ANGLE, governor); + this.strategy = await MockStrategy.new(this.managerBTC.address, this.wBTC.address); + await this.managerBTC.addStrategy(this.strategy.address, BASE_PARAMS.div(new BN('2')), { from: governor }); + await this.wBTC.mint(this.managerBTC.address, BASE); + await this.wBTC.mint(this.strategy.address, BASE); + await this.wBTC.setAllowance(this.strategy.address, this.managerBTC.address); + await this.managerBTC.setInterestsForSurplus(BASE_PARAMS.div(new BN('2')), { from: governor }); + await this.managerBTC.setSurplusConverter(guardian, { from: guardian }); + // Minting some sanTokens + await this.wBTC.approve(this.stableMaster.address, BASE, { from: user }); + await this.wBTC.mint(user, BASE); + await this.stableMaster.deposit(BASE, user, this.managerBTC.address, { from: user }); + }); + it('report - with a profit', async () => { + // const colData = await this.stableMaster.collateralMap(this.managerBTC.address); + await this.strategy.report(BASE_PARAMS, 0, 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('2'))); + await this.managerBTC.pushSurplus({ from: guardian }); + expect(await this.wBTC.balanceOf(guardian)).to.be.bignumber.equal(BASE_PARAMS.div(new BN('2'))); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + }); + it('report - with a loss smaller than interests accumulated', async () => { + await this.strategy.report(BASE_PARAMS.div(new BN('2')), 0, 0); + await this.strategy.report(0, BASE_PARAMS.div(new BN('4')), 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('8'))); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(new BN('0')); + }); + it('report - with a loss bigger than interests accumulated', async () => { + await this.strategy.report(0, BASE_PARAMS.div(new BN('2')), 0); + // The loss is BASE_PARAMS / 2, and BASE_PARAMS / 8 have been taken up by accumulated interests + // So the sanRate should decrease see a loss of 3/8 * BASE_PARAMS + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('8'))); + }); + it('recoverERC20 - reverts - too big amount', async () => { + await this.managerBTC.updateStrategyDebtRatio(this.strategy.address, 0, { from: guardian }); + let totalAssets = await this.managerBTC.getTotalAsset(); + let balance = await this.managerBTC.getBalance(); + // make the balance and total assets equal for simplicity reasons + await this.strategy.report(0, totalAssets.sub(balance), 0); + totalAssets = await this.managerBTC.getTotalAsset(); + balance = await this.managerBTC.getBalance(); + // faking some increase gain on pool manager + await this.wBTC.mint(this.managerBTC.address, BASE); + totalAssets = await this.managerBTC.getTotalAsset(); + balance = await this.managerBTC.getBalance(); + const collatData = await this.stableMaster.collateralMap(this.managerBTC.address); + const sanTokenSupply = await this.sanBTC_EUR.totalSupply(); + const interestsAccumulated = await this.managerBTC.interestsAccumulated(); + const stocksUsers = collatData.stocksUsers; + const oracleRate = await this.oracleBTC.readUpper(); + const maxAmount = sanTokenSupply + .mul(collatData.sanRate) + .div(BASE) + .add(stocksUsers.mul(collatData.collatBase).div(oracleRate)) + .add(interestsAccumulated); + + const tooMuch = balance.sub(maxAmount).add(BASE); + await expectRevert(this.managerBTC.recoverERC20(this.wBTC.address, user, tooMuch, { from: governor }), '66'); + }); + it('recoverERC20 - success - works fine', async () => { + const collatData = await this.stableMaster.collateralMap(this.managerBTC.address); + const sanTokenSupply = await this.sanBTC_EUR.totalSupply(); + const interestsAccumulated = await this.managerBTC.interestsAccumulated(); + const stocksUsers = collatData.stocksUsers; + const oracleRate = await this.oracleBTC.readUpper(); + const maxAmount = sanTokenSupply + .mul(collatData.sanRate) + .div(BASE) + .add(stocksUsers.mul(collatData.collatBase).div(oracleRate)) + .add(interestsAccumulated); + const balance = await this.managerBTC.getBalance(); + const perfectAmount = balance.sub(maxAmount); + const receipt = await this.managerBTC.recoverERC20(this.wBTC.address, user, perfectAmount, { + from: governor, + }); + + expectEvent(receipt, 'Recovered', { + token: this.wBTC.address, + to: user, + amount: perfectAmount, + }); + }); + }); + describe('report - with debtAdmin non null', () => { + it('init ', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC, this.feeManager] = + await initCollateral('wBTC', this.stableMaster, this.ANGLE, governor); + this.strategy = await MockStrategy.new(this.managerBTC.address, this.wBTC.address); + await this.managerBTC.addStrategy(this.strategy.address, BASE_PARAMS.div(new BN('2')), { from: governor }); + await this.wBTC.mint(this.managerBTC.address, BASE); + await this.wBTC.mint(this.strategy.address, BASE); + await this.wBTC.setAllowance(this.strategy.address, this.managerBTC.address); + await this.managerBTC.setInterestsForSurplus(BASE_PARAMS.div(new BN('2')), { from: governor }); + await this.managerBTC.setSurplusConverter(guardian, { from: guardian }); + // Minting some sanTokens + await this.wBTC.approve(this.stableMaster.address, BASE, { from: user }); + await this.wBTC.mint(user, BASE); + await this.stableMaster.deposit(BASE, user, this.managerBTC.address, { from: user }); + await this.strategy.report(BASE, 0, 0); + await this.managerBTC.pushSurplus({ from: guardian }); + }); + it('report - with a loss', async () => { + // const colData = await this.stableMaster.collateralMap(this.managerBTC.address); + await this.strategy.report(0, BASE_PARAMS, 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('2'))); + }); + it('report - with a gain larger than the adminDebt', async () => { + await this.strategy.report(BASE_PARAMS.mul(new BN('2')), 0, 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('2'))); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(new BN('0')); + }); + it('report - with a gain smaller than the adminDebt', async () => { + await this.strategy.report(0, BASE_PARAMS.mul(new BN('2')), 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('2'))); + await this.strategy.report(BASE_PARAMS.div(new BN('2')), 0, 0); + expect(await this.managerBTC.interestsAccumulated()).to.be.bignumber.equal(new BN('0')); + expect(await this.managerBTC.adminDebt()).to.be.bignumber.equal(BASE_PARAMS.div(new BN('4'))); + }); + }); + }); +}); diff --git a/test/strategies/Strategy.test.js b/test/strategies/Strategy.test.js new file mode 100644 index 0000000..3b4c6a1 --- /dev/null +++ b/test/strategies/Strategy.test.js @@ -0,0 +1,1243 @@ +const { ZERO_ADDRESS } = require('@openzeppelin/test-helpers/src/constants'); +const { BN } = require('@openzeppelin/test-helpers/src/setup'); +const { artifacts } = require('hardhat'); +const { + // utils + ether, + expectRevert, + expect, + expectApprox, + expectEvent, + time, + Strategy, + MockToken, + MockOracle, + MockStrategy, + BASE, + BASE_PARAMS, + BASE_ORACLE, + // functions + initAngle, + initCollateral, + initStrategy, +} = require('../helpers'); + +// Start test block +contract('Strategy', accounts => { + const [governor, guardian, user, tester] = accounts; + before(async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI] = await initCollateral( + 'DAI', + this.stableMaster, + this.ANGLE, + governor, + new BN('18'), + ); + this.oracleETHWant = await MockOracle.new(BASE_ORACLE, new BN('18')); + + // The default debt ratio of the strategy is 0.8 + [ + this.comp, + this.compound, + this.uniswapRouter, + this.uniswapPool, + this.genericCompound, + this.strategy, + this.uniswapV2Router, + this.comptroller, + ] = await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + + this.genericCompound2 = await artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ); + + this.weth = await MockToken.new('WETH', 'WETH', 18); + + this.strategy2 = await Strategy.new(this.managerBTC.address, this.ANGLE.address, [governor], guardian); + + this.genericCompound3 = await artifacts + .require('GenericCompound') + .new( + this.strategy2.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ); + this.SLPhash = web3.utils.soliditySha3('SLP'); + + this.minWindow = new BN('1000'); + + this.maxWindow = new BN('10000'); + + this.supplySpeed = await this.comptroller.price(); + this.blocksPerYear = new BN('2350000'); + }); + + describe('Initialization', () => { + describe('Parameters', () => { + it('poolManager', async () => { + expect(await this.strategy.poolManager()).to.be.equal(this.managerBTC.address); + }); + it('want', async () => { + expect(await this.strategy.want()).to.be.equal(this.wBTC.address); + }); + it('rewards', async () => { + expect(await this.strategy.rewards()).to.be.equal(this.ANGLE.address); + }); + it('BASE', async () => { + expect(await this.strategy.BASE()).to.be.bignumber.equal(BASE); + }); + it('SECONDSPERYEAR', async () => { + expect(await this.strategy.SECONDSPERYEAR()).to.be.bignumber.equal(new BN('31556952')); + }); + it('debtThreshold', async () => { + expect(await this.strategy.debtThreshold()).to.be.bignumber.equal(BASE.mul(new BN('100'))); + }); + it('minReportDelay', async () => { + expect(await this.strategy.minReportDelay()).to.be.bignumber.equal(new BN('0')); + }); + it('maxReportDelay', async () => { + expect(await this.strategy.maxReportDelay()).to.be.bignumber.equal(new BN('86400')); + }); + it('minimumAmountMoved', async () => { + expect(await this.strategy.minimumAmountMoved()).to.be.bignumber.equal(new BN('0')); + }); + it('rewardAmount', async () => { + expect(await this.strategy.rewardAmount()).to.be.bignumber.equal(new BN('0')); + }); + it('emergencyExit', async () => { + expect(await this.strategy.emergencyExit()).to.be.equal(false); + }); + it('allowance', async () => { + expect(await this.wBTC.allowance(this.strategy.address, this.managerBTC.address)).to.be.bignumber.equal( + new BN(2).pow(new BN(256)).sub(new BN(1)), + ); + }); + }); + + describe('AccessControl', () => { + it('guardian role', async () => { + this.guardianRole = web3.utils.soliditySha3('GUARDIAN_ROLE'); + this.managerRole = web3.utils.soliditySha3('POOLMANAGER_ROLE'); + this.guardianError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.guardianRole}`; + this.managerError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.managerRole}`; + + expect(await this.strategy.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), guardian)).to.be.equal(true); + expect(await this.strategy.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), governor)).to.be.equal(true); + }); + it('manager role', async () => { + expect( + await this.strategy.hasRole(web3.utils.soliditySha3('POOLMANAGER_ROLE'), this.managerBTC.address), + ).to.be.equal(true); + }); + it('withdraw - reverts nonManager', async () => { + await expectRevert(this.strategy.withdraw(BASE, { from: user }), this.managerError); + }); + it('setEmergencyExit - reverts nonManager', async () => { + await expectRevert(this.strategy.setEmergencyExit({ from: user }), this.managerError); + }); + it('setRewards - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setRewards(this.wBTC.address, { from: user }), this.guardianError); + }); + it('setRewardAmount - reverts nonGuardian', async () => { + await expectRevert( + this.strategy.setRewardAmountAndMinimumAmountMoved(BASE, BASE, { from: user }), + this.guardianError, + ); + }); + it('setMinReportDelay - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setMinReportDelay(BASE, { from: user }), this.guardianError); + }); + it('setMaxReportDelay - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setMaxReportDelay(BASE, { from: user }), this.guardianError); + }); + it('setDebtThreshold - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setDebtThreshold(BASE, { from: user }), this.guardianError); + }); + it('sweep - reverts nonGuardian', async () => { + await expectRevert(this.strategy.sweep(this.wBTC.address, user, { from: user }), this.guardianError); + }); + it('manualAllocation - reverts nonGuardian', async () => { + this.newPositions = [{ lender: this.genericCompound.address, share: 1100 }]; + await expectRevert(this.strategy.manualAllocation(this.newPositions, { from: user }), this.guardianError); + }); + it('setWithdrawalThreshold - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setWithdrawalThreshold(BASE, { from: user }), this.guardianError); + }); + it('addLender - reverts nonGuardian', async () => { + await expectRevert(this.strategy.addLender(user, { from: user }), this.guardianError); + }); + it('safeRemoveLender - reverts nonGuardian', async () => { + await expectRevert(this.strategy.safeRemoveLender(user, { from: user }), this.guardianError); + }); + it('forceRemoveLender - reverts nonGuardian', async () => { + await expectRevert(this.strategy.forceRemoveLender(user, { from: user }), this.guardianError); + }); + it('addGuardian - reverts nonGuardian', async () => { + await expectRevert(this.strategy.addGuardian(this.wBTC.address, { from: user }), this.managerError); + }); + it('revokeGuardian - reverts nonGuardian', async () => { + await expectRevert(this.strategy.revokeGuardian(this.wBTC.address, { from: user }), this.managerError); + }); + }); + }); + + describe('debtRatio', () => { + it('success - set correctly for strategy', async () => { + const debtRatio = (await this.managerBTC.strategies(this.strategy.address)).debtRatio; + expect(debtRatio).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('8')).div(new BN('10'))); + }); + it('success - set correctly for manager', async () => { + expect(await this.managerBTC.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('8')).div(new BN('10'))); + }); + }); + + describe('setGuardian - when there is a strategy', () => { + it('success - adding a new guardian', async () => { + await this.core.setGuardian(tester, { from: governor }); + expect(await this.managerBTC.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), tester)).to.be.equal(true); + expect(await this.managerBTC.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), guardian)).to.be.equal(false); + }); + it('success - resetting guardian', async () => { + await this.core.setGuardian(guardian, { from: governor }); + }); + }); + + describe('estimatedAPR', () => { + it('success - returns 0 when no asset', async () => { + expect(await this.strategy.estimatedAPR()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('harvest', () => { + it('init - minting on poolManager', async () => { + await this.wBTC.mint(this.managerBTC.address, ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(BASE.mul(new BN('10'))); + }); + + it('success - lent assets updated', async () => { + await this.strategy.harvest(); + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // But 8 lent from manager to strategy + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('2')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + // These 8 are then given to the lender + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.managerBTC.totalDebt()).to.be.bignumber.equal(ether('8')); + expect((await this.managerBTC.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('8'), + ); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('8')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.lentTotalAssets()).to.be.bignumber.equal(ether('8')); + }); + + it('setting - creation of debt for the strategy', async () => { + await this.managerBTC.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('5')).div(new BN('10')), + { from: governor }, + ); + expect((await this.managerBTC.strategies(this.strategy.address)).debtRatio).to.be.bignumber.equal( + BASE_PARAMS.mul(new BN('5')).div(new BN('10')), + ); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + }); + it('success - manager debt ratio check', async () => { + expect(await this.managerBTC.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('5')).div(new BN('10'))); + }); + + it('updateStrategyDebtRatio reverts', async () => { + await expectRevert( + this.managerBTC.updateStrategyDebtRatio(tester, BASE_PARAMS.mul(new BN('5')).div(new BN('10')), { + from: governor, + }), + '78', + ); + await expectRevert( + this.managerBTC.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('11')).div(new BN('10')), + { from: governor }, + ), + '76', + ); + }); + + it('success - harvesting with debt', async () => { + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // These 5 are then given to the lender + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + }); + }); + + describe('withdraw', () => { + it('reverts - invalid strategy', async () => { + await expectRevert(this.managerBTC.withdrawFromStrategy(governor, ether('1'), { from: governor }), '78'); + }); + + it('success - amount withdrawn', async () => { + this.initialDebt = await this.managerBTC.totalDebt(); + await this.managerBTC.withdrawFromStrategy(this.strategy.address, ether('1'), { from: governor }); + // 1 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('6')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('4')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // 4 are given to the lender + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('4')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + }); + + it('success - totalDebt updated', async () => { + expect(await this.managerBTC.totalDebt()).to.be.bignumber.equal(this.initialDebt.sub(ether('1'))); + const totalDebt = (await this.managerBTC.strategies(this.strategy.address)).totalStrategyDebt; + expect(totalDebt).to.be.bignumber.equal(this.initialDebt.sub(ether('1'))); + }); + + it('success - harvesting - lent assets updated', async () => { + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // 5 lent from manager to strategy + // 5 are given to the lender + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + }); + }); + + describe('harvestTrigger', () => { + it('reverts - invalid strategy', async () => { + await expectRevert(this.managerBTC.withdrawFromStrategy(governor, ether('1'), { from: governor }), '78'); + }); + it('success - call too soon', async () => { + const minReportDelay = await this.strategy.minReportDelay({ from: governor }); + await this.strategy.setMinReportDelay(this.minWindow, { from: governor }); + expect(await this.strategy.harvestTrigger({ from: user })).to.be.equal(false); + await this.strategy.setMinReportDelay(minReportDelay, { from: governor }); + }); + it('success - call after maxReportDelay ', async () => { + const maxReportDelay = await this.strategy.maxReportDelay({ from: governor }); + await this.strategy.setMaxReportDelay(0, { from: governor }); + expect(await this.strategy.harvestTrigger({ from: user })).to.be.equal(true); + await this.strategy.setMaxReportDelay(maxReportDelay, { from: governor }); + }); + it('success - Outstanding > debtThreshold', async () => { + await this.strategy.setDebtThreshold(ether('1'), { from: governor }); + await this.managerBTC.updateStrategyDebtRatio(this.strategy.address, ether('0'), { from: governor }); + expect(await this.strategy.harvestTrigger({ from: user })).to.be.equal(true); + await this.strategy.setDebtThreshold(ether('0'), { from: governor }); + await this.managerBTC.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('5')).div(new BN('10')), + { from: governor }, + ); + }); + it('success - feeManager should not call', async () => { + await this.strategy.setRewardAmountAndMinimumAmountMoved(0, BASE, { from: governor }); + expect(await this.strategy.harvestTrigger({ from: user })).to.be.equal(false); + }); + it('success - feeManager should call', async () => { + await this.wBTC.mint(this.strategy.address, ether('10'), { from: guardian }); + expect(await this.strategy.harvestTrigger({ from: user })).to.be.equal(true); + await this.wBTC.burn(this.strategy.address, ether('10'), { from: guardian }); + }); + }); + + describe('removeLender', () => { + it('reverts - not a lender', async () => { + await expectRevert(this.strategy.safeRemoveLender(tester, { from: governor }), '94'); + }); + + it('success - lender removed', async () => { + await this.strategy.safeRemoveLender(this.genericCompound.address, { from: governor }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('5')); + }); + + it('withdraw - success', async () => { + await this.managerBTC.withdrawFromStrategy(this.strategy.address, ether('1'), { from: governor }); + // 1 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('6')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('4')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + }); + + it('success - harvesting - assets updated', async () => { + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + }); + }); + + describe('addLender', () => { + it('success - lender added', async () => { + await this.strategy.addLender(this.genericCompound.address, { from: governor }); + }); + it('reverts - strategy already added', async () => { + await expectRevert(this.strategy.addLender(this.genericCompound.address, { from: governor }), '97'); + }); + it('reverts - undockedLender', async () => { + await expectRevert(this.strategy.addLender(this.genericCompound3.address, { from: governor }), '96'); + }); + + it('success - harvesting - assets updated', async () => { + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + + // Still 10 total assets + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // 5 lent from manager to strategy + // 5 are given to the lender + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + }); + }); + + describe('forceRemoveLender', () => { + it('init - adding another lender / harvesting', async () => { + await this.strategy.addLender(this.genericCompound2.address, { from: governor }); + await this.strategy.harvest(); + }); + + it('success', async () => { + await this.strategy.forceRemoveLender(this.genericCompound2.address, { from: governor }); + }); + }); + + describe('revokeStrategy', () => { + it('reverts - invalid debtRatio', async () => { + await expectRevert(this.managerBTC.revokeStrategy(this.strategy.address, { from: governor }), '77'); + }); + + it('reverts - funds not withdrawn', async () => { + await this.managerBTC.updateStrategyDebtRatio(this.strategy.address, ether('0'), { from: governor }); + await expectRevert(this.managerBTC.revokeStrategy(this.strategy.address, { from: governor }), '77'); + }); + + it('reverts - invalid strategy', async () => { + await expectRevert(this.managerBTC.revokeStrategy(tester, { from: governor }), '78'); + }); + + it('success - strategy revoked', async () => { + await this.strategy.harvest(); + await this.managerBTC.revokeStrategy(this.strategy.address, { from: governor }); + expect( + await this.managerBTC.hasRole(web3.utils.soliditySha3('STRATEGY_ROLE'), this.strategy.address), + ).to.be.equal(false); + }); + }); + + describe('addStrategy', () => { + it('reverts - invalid address', async () => { + await expectRevert( + this.managerBTC.addStrategy(ZERO_ADDRESS, BASE_PARAMS.mul(new BN('6')).div(new BN('10')), { from: governor }), + '0', + ); + }); + + it('reverts - wrong manager', async () => { + const mockStrategy = await artifacts + .require('Strategy') + .new(this.managerDAI.address, this.ANGLE.address, [governor], guardian); + + await expectRevert( + this.managerBTC.addStrategy(mockStrategy.address, BASE_PARAMS.mul(new BN('6')).div(new BN('10')), { + from: governor, + }), + '74', + ); + }); + + it('reverts - invalid want', async () => { + const strat = await MockStrategy.new(this.managerBTC.address, user); + await expectRevert( + this.managerBTC.addStrategy(strat.address, BASE_PARAMS.mul(new BN('6')).div(new BN('10')), { from: governor }), + '75', + ); + }); + + it('success - strategy added', async () => { + await this.managerBTC.addStrategy(this.strategy.address, BASE_PARAMS.mul(new BN('5')).div(new BN('10')), { + from: governor, + }); + }); + + it('reverts - already added', async () => { + await expectRevert( + this.managerBTC.addStrategy(this.strategy.address, BASE_PARAMS.mul(new BN('5')).div(new BN('10')), { + from: governor, + }), + '73', + ); + }); + }); + describe('deploy Strategy', () => { + it('reverts - rewards zero address', async () => { + await expectRevert( + artifacts.require('Strategy').new(this.managerBTC.address, ZERO_ADDRESS, [governor], guardian), + '0', + ); + }); + + it('reverts - rewards same as want', async () => { + await expectRevert( + artifacts.require('Strategy').new(this.managerBTC.address, this.wBTC.address, [governor], guardian), + '92', + ); + }); + + it('reverts - governor zero address', async () => { + await expectRevert( + artifacts.require('Strategy').new(this.managerBTC.address, this.ANGLE.address, [ZERO_ADDRESS], guardian), + '0', + ); + }); + it('reverts guardian zero address', async () => { + await expectRevert( + artifacts.require('Strategy').new(this.managerBTC.address, this.ANGLE.address, [governor], ZERO_ADDRESS), + '0', + ); + }); + it('reverts - guardian zero address', async () => { + await expectRevert.unspecified( + artifacts.require('Strategy').new(ZERO_ADDRESS, this.ANGLE.address, [governor], guardian), + ); + }); + + it('reverts - debt Ratio too high', async () => { + const mockStrategy = await artifacts + .require('Strategy') + .new(this.managerBTC.address, this.ANGLE.address, [governor], guardian); + + await expectRevert( + this.managerBTC.addStrategy(mockStrategy.address, BASE_PARAMS.mul(new BN('6')).div(new BN('10')), { + from: governor, + }), + '76', + ); + }); + + it('addStrategy - success with two other strategies', async () => { + this.mockStrategy1 = await artifacts + .require('Strategy') + .new(this.managerBTC.address, this.ANGLE.address, [governor], guardian); + await this.managerBTC.addStrategy(this.mockStrategy1.address, BASE_PARAMS.mul(new BN('1')).div(new BN('10')), { + from: governor, + }); + this.mockStrategy2 = await artifacts + .require('Strategy') + .new(this.managerBTC.address, this.ANGLE.address, [governor], guardian); + await this.managerBTC.addStrategy(this.mockStrategy2.address, BASE_PARAMS.mul(new BN('1')).div(new BN('10')), { + from: governor, + }); + }); + + it('revokeStrategy - success two strategies', async () => { + await this.managerBTC.updateStrategyDebtRatio(this.mockStrategy1.address, ether('0'), { from: governor }); + await this.managerBTC.updateStrategyDebtRatio(this.mockStrategy2.address, ether('0'), { from: governor }); + await this.managerBTC.revokeStrategy(this.mockStrategy1.address, { from: governor }); + await this.managerBTC.revokeStrategy(this.mockStrategy2.address, { from: governor }); + expect( + await this.managerBTC.hasRole(web3.utils.soliditySha3('STRATEGY_ROLE'), this.mockStrategy2.address), + ).to.be.equal(false); + expect( + await this.managerBTC.hasRole(web3.utils.soliditySha3('STRATEGY_ROLE'), this.mockStrategy1.address), + ).to.be.equal(false); + }); + }); + + describe('lendStatuses', () => { + it('success', async () => { + await this.strategy.harvest(); + expect((await this.strategy.lendStatuses())[0].assets).to.be.bignumber.equal(ether('5')); + }); + }); + + describe('estimatedAPR', () => { + it('success', async () => { + const cTokenSupply = await this.compound.totalSupply(); + const exchangeRate = await this.compound.exchangeRateStored(); + const supplyInWant = cTokenSupply.mul(exchangeRate).div(BASE); + + const compInWant = this.supplySpeed.mul(new BN('10')); + const incentivesRate = compInWant + .mul(this.blocksPerYear) + .mul(BASE) + .div(supplyInWant) + .mul(new BN(95)) + .div(new BN('100')); + + expectApprox(await this.strategy.estimatedAPR(), ether('0.04').add(incentivesRate)); + }); + }); + + describe('estimatedAPR - manager level', () => { + it('success - without SLP', async () => { + expect(await this.managerBTC.estimatedAPR()).to.be.bignumber.equal(new BN(2).pow(new BN(256)).sub(new BN(1))); + }); + + it('success - with SLP', async () => { + await this.wBTC.mint(user, ether('10')); + await this.wBTC.approve(this.stableMaster.address, ether('10'), { from: user }); + await this.stableMaster.deposit(ether('10'), user, this.managerBTC.address, { from: user }); + const cTokenSupply = await this.compound.totalSupply(); + const exchangeRate = await this.compound.exchangeRateStored(); + const supplyInWant = cTokenSupply.mul(exchangeRate).div(BASE); + + const compInWant = this.supplySpeed.mul(new BN('10')); + const incentivesRate = compInWant + .mul(this.blocksPerYear) + .mul(BASE) + .div(supplyInWant) + .mul(new BN(95)) + .div(new BN('100')); + expectApprox( + await this.managerBTC.estimatedAPR(), + BASE_PARAMS.mul(new BN('2')) + .div(new BN('100')) + .add(incentivesRate.mul(new BN('5')).div(new BN('10')).div(BASE_PARAMS)), + ); + await this.stableMaster.withdraw(ether('10'), user, user, this.managerBTC.address, { from: user }); + }); + }); + + describe('numLenders', () => { + it('success', async () => { + expect(await this.strategy.numLenders()).to.be.bignumber.equal(new BN(1)); + }); + }); + + describe('sweep', () => { + it('reverts - access control', async () => { + await expectRevert.unspecified(this.strategy.sweep(this.comp.address, user, { from: user })); + }); + + it('reverts - protected token', async () => { + await this.ANGLE.mint(this.strategy.address, ether('1')); + await expectRevert(this.strategy.sweep(this.wBTC.address, user, { from: governor }), '93'); + }); + + it('success - balance updated', async () => { + await this.strategy.sweep(this.ANGLE.address, user, { from: governor }); + expect(await this.ANGLE.balanceOf(user)).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('setMinReportDelay', () => { + it('success', async () => { + await this.strategy.setMinReportDelay(this.minWindow, { from: governor }); + expect(await this.strategy.minReportDelay()).to.be.bignumber.equal(this.minWindow); + }); + }); + + describe('setMaxReportDelay', () => { + it('success', async () => { + await this.strategy.setMaxReportDelay(this.maxWindow, { from: governor }); + expect(await this.strategy.maxReportDelay()).to.be.bignumber.equal(this.maxWindow); + }); + }); + + describe('setDebtThreshold', () => { + it('success', async () => { + await this.strategy.setDebtThreshold(ether('1'), { from: governor }); + expect(await this.strategy.debtThreshold()).to.be.bignumber.equal(ether('1')); + }); + }); + + describe('setWithdrawalThreshold', () => { + it('success', async () => { + await this.strategy.setWithdrawalThreshold(ether('1'), { from: governor }); + expect(await this.strategy.withdrawalThreshold()).to.be.bignumber.equal(ether('1')); + }); + it('success - resets', async () => { + await this.strategy.setWithdrawalThreshold(BASE.div(new BN('10000')), { from: governor }); + expect(await this.strategy.withdrawalThreshold()).to.be.bignumber.equal(BASE.div(new BN('10000'))); + }); + }); + + describe('setRewards', () => { + it('reverts - incorrect address', async () => { + await expectRevert(this.strategy.setRewards(ZERO_ADDRESS, { from: governor }), '92'); + }); + it('success', async () => { + await this.strategy.setRewards(this.DAI.address, { from: governor }); + expect(await this.strategy.rewards()).to.be.equal(this.DAI.address); + }); + it('success - resets', async () => { + await this.strategy.setRewards(this.ANGLE.address, { from: governor }); + expect(await this.strategy.rewards()).to.be.equal(this.ANGLE.address); + }); + }); + + describe('setRewardAmount and harvest trigger', () => { + it('success - balance updated', async () => { + // Setting the rewardAmount + await this.strategy.setRewardAmountAndMinimumAmountMoved(ether('3'), ether('7'), { from: governor }); + expect(await this.strategy.rewardAmount()).to.be.bignumber.equal(ether('3')); + expect(await this.strategy.minimumAmountMoved()).to.be.bignumber.equal(ether('7')); + + await this.ANGLE.mint(this.strategy.address, ether('1000000')); + // Changing the last report timestamp + await this.strategy.harvest({ from: user }); + // Making time pass over maxReportDelay + await time.increase(this.maxWindow.mul(new BN('2'))); + }); + + it('success - harvest updates balance', async () => { + const balance = await this.ANGLE.balanceOf(user); + await this.strategy.harvest({ from: user }); + const balance2 = await this.ANGLE.balanceOf(user); + expect(balance2).to.be.bignumber.equal(balance.add(ether('3'))); + }); + }); + + describe('isActive', () => { + it('success', async () => { + const receipt = await this.strategy.isActive({ from: governor }); + expect(receipt).to.be.equal(true); + }); + }); + + describe('harvest with profit and loss', () => { + it('init', async () => { + await this.strategy.harvest(); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5')); + }); + + it('success - updated Compound Exchange Rate', async () => { + // Minting the tokens for the capital gain made on Compound + await this.wBTC.mint(this.compound.address, ether('10000')); + await this.compound.updateExchangeRate(ether('2')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('10')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('10')); + }); + + it('success - profit registered', async () => { + const receipt = await this.strategy.harvest(); + expectEvent.inTransaction(receipt.tx, this.managerBTC, 'FeesDistributed', { + amountDistributed: ether('5'), + }); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('15')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('7.5')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('7.5')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('7.5')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + }); + + it('success - harvest with loss', async () => { + await this.compound.updateExchangeRate(ether('1')); + // The value of the total assets is now 3.75, so the total value is now 11.25 + // In the end the total assets will be 11.25/2 = 5.625 + // The loss here is 3.75 + await this.strategy.harvest(); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('11.25')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5.625')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5.625')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('5.625')); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + }); + + it('init - creates SLPs', async () => { + await this.wBTC.mint(user, ether('1000')); + await this.wBTC.approve(this.stableMaster.address, ether('1000'), { from: user }); + await this.stableMaster.deposit(ether('1'), user, this.managerBTC.address, { from: user }); + // 1 has been deposited by SLPs + expect(await this.sanBTC_EUR.balanceOf(user)).to.be.bignumber.equal(ether('1')); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('12.25')); + this.sanRate = (await this.stableMaster.collateralMap(this.managerBTC.address)).sanRate; + }); + + it('success - updating exchange rate first for a small loss', async () => { + await this.compound.updateExchangeRate(ether('0.9')); + // The exchange rate decreases from 1 to 0.9, meaning the value of the tokens in the strategy is 0.9 * 5.625 + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('5.0625')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5.0625')); + }); + + it('success - harvest with small loss and sanTokens', async () => { + await this.strategy.harvest(); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('11.6875')); + // The strategy should have 10.6875/2 + expectApprox(await this.strategy.estimatedTotalAssets(), ether('5.84375')); + expectApprox(await this.genericCompound.nav(), ether('5.84375')); + expectApprox(await this.wBTC.balanceOf(this.managerBTC.address), ether('5.84375')); + }); + + it('success - new sanRate updated', async () => { + // The Loss is ether('0.5625') + expect((await this.stableMaster.collateralMap(this.managerBTC.address)).sanRate).to.be.bignumber.equal( + ether('0.4375'), + ); + }); + + it('success - updating exchange rate first for a big loss', async () => { + // Exchange rate is divided by two + await this.compound.updateExchangeRate(ether('0.45')); + expectApprox(await this.genericCompound.nav(), ether('2.921875')); + expectApprox(await this.strategy.estimatedTotalAssets(), ether('2.921875')); + }); + + it('success - harvest with big loss and sanTokens', async () => { + await this.strategy.harvest(); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expectApprox(await this.managerBTC.getTotalAsset(), ether('8.715625')); + }); + + it('success - checking for new sanRate', async () => { + // The Loss is ether('0.5625') + expect((await this.stableMaster.collateralMap(this.managerBTC.address)).sanRate).to.be.bignumber.equal( + new BN('1'), + ); + }); + it('success - unpause SLPs', async () => { + await this.stableMaster.unpause(this.SLPhash, this.managerBTC.address, { from: this.governor }); + const hash = web3.utils.soliditySha3( + { t: 'bytes32', v: this.SLPhash }, + { t: 'address', v: this.managerBTC.address }, + ); + expect(await this.stableMaster.paused(hash)).to.be.equal(false); + }); + }); + + describe('creditAvailable', () => { + it('success', async () => { + expect(await this.managerBTC.creditAvailable({ from: tester })).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('manualAllocation', () => { + it('reverts - too high shares', async () => { + this.newPositions = [{ lender: this.genericCompound.address, share: 1100 }]; + await expectRevert( + this.strategy.manualAllocation(this.newPositions, { from: governor }), + 'ERC20: transfer amount exceeds balance', + ); + }); + it('reverts - invalid shares', async () => { + this.newPositions = [{ lender: this.genericCompound.address, share: 900 }]; + await expectRevert(this.strategy.manualAllocation(this.newPositions, { from: governor }), '95'); + }); + it('reverts - invalid lender', async () => { + this.newPositions = [{ lender: this.genericCompound2.address, share: 1000 }]; + await expectRevert(this.strategy.manualAllocation(this.newPositions, { from: governor }), '94'); + }); + it('success - positions updated', async () => { + this.newPositions = [{ lender: this.genericCompound.address, share: 1000 }]; + await this.strategy.manualAllocation(this.newPositions, { from: governor }); + }); + }); + + describe('setEmergencyExit', () => { + it('success - works fine', async () => { + this.totalAsset = await this.managerBTC.getTotalAsset(); + await this.managerBTC.setStrategyEmergencyExit(this.strategy.address, { from: governor }); + }); + it('success - emergencyExit parameter updated', async () => { + expect(await this.strategy.emergencyExit()).to.be.equal(true); + }); + it('success - Strategy debtRatio updated', async () => { + const debtRatio = (await this.managerBTC.strategies(this.strategy.address)).debtRatio; + expect(debtRatio).to.be.bignumber.equal(new BN('0')); + }); + it('success - Manager debtRatio updated', async () => { + expect(await this.managerBTC.debtRatio()).to.be.bignumber.equal(new BN('0')); + }); + + it('success - harvest check', async () => { + expectApprox(await this.managerBTC.getTotalAsset(), this.totalAsset); + expectApprox(await this.wBTC.balanceOf(this.managerBTC.address), this.totalAsset); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.wBTC.balanceOf(this.genericCompound.address)).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('0')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('0')); + }); + }); + + describe('setEmergencyExit - harvest amount freed = debt outstanding', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI] = await initCollateral( + 'DAI', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + // The default debt ratio of the strategy is 0.8 + [this.comp, this.compound, this.uniswapRouter, this.uniswapPool, this.genericCompound, this.strategy] = + await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + await this.wBTC.mint(this.managerBTC.address, ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + await this.strategy.harvest(); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // But 8 lent from manager to strategy + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('2')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + }); + + it('success - parameter = true', async () => { + // This automatically harvests + await this.managerBTC.setStrategyEmergencyExit(this.strategy.address, { from: governor }); + expect(await this.strategy.emergencyExit()).to.be.equal(true); + }); + }); + + describe('setEmergencyExit - harvest amount freed > debt outstanding', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI] = await initCollateral( + 'DAI', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + // The default debt ratio of the strategy is 0.8 + [this.comp, this.compound, this.uniswapRouter, this.uniswapPool, this.genericCompound, this.strategy] = + await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + + await this.wBTC.mint(this.managerBTC.address, ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + await this.strategy.harvest(); + expect(await this.managerBTC.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // But 8 lent from manager to strategy + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('2')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + }); + it('update Compound Exchange Rate - success', async () => { + // Minting the tokens for the capital gain made on Compound + await this.wBTC.mint(this.compound.address, ether('10000')); + await this.compound.updateExchangeRate(ether('2')); + expect(await this.genericCompound.nav()).to.be.bignumber.equal(ether('16')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('16')); + }); + it('success - emergencyExit prepared', async () => { + // This automatically harvests + await this.managerBTC.setStrategyEmergencyExit(this.strategy.address, { from: governor }); + expect(await this.strategy.emergencyExit()).to.be.equal(true); + }); + }); + + describe('withdrawSome', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI] = await initCollateral( + 'DAI', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + // The default debt ratio of the strategy is 0.8 + [this.comp, this.compound, this.uniswapRouter, this.uniswapPool, this.genericCompound, this.strategy] = + await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + + await this.wBTC.mint(this.managerBTC.address, ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + await this.strategy.harvest(); + }); + it('withdrawFromStrategy - success - small amount', async () => { + await this.managerBTC.withdrawFromStrategy(this.strategy.address, new BN('1'), { from: governor }); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('2')); + }); + it('removeLender - success', async () => { + // This automatically harvests + await this.strategy.safeRemoveLender(this.genericCompound.address, { from: governor }); + expect(await this.wBTC.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('8')); + }); + it('withdrawFromStrategy - success - withdraw important amount when there are no lenders left', async () => { + // This automatically harvests + await this.managerBTC.withdrawFromStrategy(this.strategy.address, ether('9'), { from: governor }); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + }); + }); + + describe('withdrawSome - multiple lenders', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [this.wBTC, this.oracleBTC, this.managerBTC, this.sanBTC_EUR, this.perpetualManagerBTC] = await initCollateral( + 'wBTC', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + + [this.DAI, this.oracleDAI, this.managerDAI, this.sanDAI_EUR, this.perpetualManagerDAI] = await initCollateral( + 'DAI', + this.stableMaster, + this.ANGLE, + governor, + new BN(18), + ); + // The default debt ratio of the strategy is 0.8 + [this.comp, this.compound, this.uniswapRouter, this.uniswapPool, this.genericCompound, this.strategy] = + await initStrategy('wBTC', this.wBTC, this.managerBTC, this.ANGLE, this.oracleETHWant, governor, guardian); + + this.genericCompound2 = await artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ); + + this.genericCompound3 = await artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ); + + await this.wBTC.mint(this.managerBTC.address, ether('10')); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + await this.strategy.harvest(); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('2')); + }); + it('genericCompound - constructor - reverts wrong cToken', async () => { + await expectRevert( + artifacts + .require('GenericCompound') + .new( + this.strategy2.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + 'wrong cToken', + ); + }); + it('genericCompound - constructor - reverts zero address', async () => { + await expectRevert( + artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + ZERO_ADDRESS, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + '0', + ); + + await expectRevert( + artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + ZERO_ADDRESS, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + '0', + ); + + await expectRevert( + artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + ZERO_ADDRESS, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + '0', + ); + + await expectRevert.unspecified( + artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + ZERO_ADDRESS, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + ); + + await expectRevert.unspecified( + artifacts + .require('GenericCompound') + .new( + ZERO_ADDRESS, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + this.compound.address, + [governor], + guardian, + ), + ); + + await expectRevert.unspecified( + artifacts + .require('GenericCompound') + .new( + this.strategy.address, + ' ', + this.uniswapRouter.address, + this.uniswapV2Router.address, + this.comptroller.address, + this.comp.address, + web3.utils.asciiToHex('0'), + ZERO_ADDRESS, + [governor], + guardian, + ), + ); + }); + + it('addLender - success - adding multiple', async () => { + await this.strategy.addLender(this.genericCompound3.address, { from: governor }); + await this.strategy.addLender(this.genericCompound2.address, { from: governor }); + }); + it('removeLender - success', async () => { + await this.strategy.safeRemoveLender(this.genericCompound3.address, { from: governor }); + }); + it('withdrawSome - fail - under withdrawThreshold', async () => { + await this.strategy.setWithdrawalThreshold(ether('9')); + const totalStrategyDebtPre = (await this.managerBTC.strategies(this.strategy.address)).totalStrategyDebt; + await this.managerBTC.withdrawFromStrategy(this.strategy.address, ether('8'), { from: governor }); + await this.strategy.setWithdrawalThreshold(ether('0')); + const totalStrategyDebtPost = (await this.managerBTC.strategies(this.strategy.address)).totalStrategyDebt; + // ether('8') is considered as dust, therefore not considered as gain --> no change of totalStrategyDebt + expect(totalStrategyDebtPre).to.be.bignumber.equal(totalStrategyDebtPost); + }); + it('withdrawSome - success - two lenders', async () => { + // This automatically harvests + await this.managerBTC.withdrawFromStrategy(this.strategy.address, ether('8'), { from: governor }); + expect(await this.wBTC.balanceOf(this.managerBTC.address)).to.be.bignumber.equal(ether('10')); + }); + }); +}); diff --git a/test/strategies/StrategyStETH.test.js b/test/strategies/StrategyStETH.test.js new file mode 100644 index 0000000..ee9ff94 --- /dev/null +++ b/test/strategies/StrategyStETH.test.js @@ -0,0 +1,641 @@ +const balance = require('@openzeppelin/test-helpers/src/balance'); +const { ZERO_ADDRESS } = require('@openzeppelin/test-helpers/src/constants'); +const { BN } = require('@openzeppelin/test-helpers/src/setup'); +const { ethers } = require('hardhat'); +const { + // utils + ether, + expectRevert, + expect, + BASE, + BASE_PARAMS, + // functions + initAngle, + initWETH, + StrategyStETHAcc, +} = require('../helpers'); + +// Start test block +contract('StrategyStETH', accounts => { + const [governor, guardian, user, tester] = accounts; + + before(async () => { + [this.owner] = await ethers.getSigners(); + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [ + this.wETH, + this.oracleETH, + this.managerETH, + this.sanETH_EUR, + this.perpetualManagerETH, + this.feeManagerETH, + this.stETH, + this.curve, + this.strategy, + ] = await initWETH(this.stableMaster, this.ANGLE, governor, guardian); + + this.minWindow = new BN('1000'); + + this.maxWindow = new BN('10000'); + this.blocksPerYear = new BN('2350000'); + }); + + describe('Initialization', () => { + describe('Parameters', () => { + it('poolManager', async () => { + expect(await this.strategy.poolManager()).to.be.equal(this.managerETH.address); + }); + it('want', async () => { + expect(await this.strategy.want()).to.be.equal(this.wETH.address); + }); + it('rewards', async () => { + expect(await this.strategy.rewards()).to.be.equal(this.ANGLE.address); + }); + it('stETH', async () => { + expect(await this.strategy.stETH()).to.be.equal(this.stETH.address); + }); + it('wETH', async () => { + expect(await this.strategy.weth()).to.be.equal(this.wETH.address); + }); + it('stableSwapSTETH', async () => { + expect(await this.strategy.stableSwapSTETH()).to.be.equal(this.curve.address); + }); + it('BASE', async () => { + expect(await this.strategy.BASE()).to.be.bignumber.equal(BASE); + }); + it('apr', async () => { + expect(await this.strategy.apr()).to.be.bignumber.equal(new BN('0')); + }); + it('SECONDSPERYEAR', async () => { + expect(await this.strategy.SECONDSPERYEAR()).to.be.bignumber.equal(new BN('31556952')); + }); + it('DENOMINATOR', async () => { + expect(await this.strategy.DENOMINATOR()).to.be.bignumber.equal(new BN('10000')); + }); + it('debtThreshold', async () => { + expect(await this.strategy.debtThreshold()).to.be.bignumber.equal(BASE.mul(new BN('100'))); + }); + it('maxSingleTrade', async () => { + expect(await this.strategy.maxSingleTrade()).to.be.bignumber.equal(BASE.mul(new BN('1000'))); + }); + it('slippageProtectionOut', async () => { + expect(await this.strategy.slippageProtectionOut()).to.be.bignumber.equal(new BN('50')); + }); + it('minReportDelay', async () => { + expect(await this.strategy.minReportDelay()).to.be.bignumber.equal(new BN('0')); + }); + it('maxReportDelay', async () => { + expect(await this.strategy.maxReportDelay()).to.be.bignumber.equal(new BN('86400')); + }); + it('minimumAmountMoved', async () => { + expect(await this.strategy.minimumAmountMoved()).to.be.bignumber.equal(new BN('0')); + }); + it('rewardAmount', async () => { + expect(await this.strategy.rewardAmount()).to.be.bignumber.equal(new BN('0')); + }); + it('emergencyExit', async () => { + expect(await this.strategy.emergencyExit()).to.be.equal(false); + }); + it('allowance - wETH', async () => { + expect(await this.wETH.allowance(this.strategy.address, this.managerETH.address)).to.be.bignumber.equal( + new BN(2).pow(new BN(256)).sub(new BN(1)), + ); + }); + it('allowance - stETH', async () => { + expect(await this.stETH.allowance(this.strategy.address, this.curve.address)).to.be.bignumber.equal( + new BN(2).pow(new BN(256)).sub(new BN(1)), + ); + }); + }); + + describe('constructor', () => { + it('reverts - zero guardian address', async () => { + await expectRevert( + StrategyStETHAcc.new( + this.managerETH.address, + this.ANGLE.address, + [governor], + ZERO_ADDRESS, + this.curve.address, + this.wETH.address, + this.stETH.address, + ), + '0', + ); + }); + it('reverts - zero governor address', async () => { + await expectRevert( + StrategyStETHAcc.new( + this.managerETH.address, + this.ANGLE.address, + [ZERO_ADDRESS], + guardian, + this.curve.address, + this.wETH.address, + this.stETH.address, + ), + '0', + ); + }); + it('reverts - zero reward address', async () => { + await expectRevert( + StrategyStETHAcc.new( + this.managerETH.address, + ZERO_ADDRESS, + [governor], + guardian, + this.curve.address, + this.wETH.address, + this.stETH.address, + ), + '0', + ); + }); + it('reverts - want != weth', async () => { + await expectRevert( + StrategyStETHAcc.new( + this.managerETH.address, + this.ANGLE.address, + [governor], + guardian, + this.curve.address, + this.stETH.address, + this.stETH.address, + ), + '20', + ); + }); + it('reverts - rewards != want', async () => { + await expectRevert( + StrategyStETHAcc.new( + this.managerETH.address, + this.wETH.address, + [governor], + guardian, + this.curve.address, + this.wETH.address, + this.stETH.address, + ), + '92', + ); + }); + }); + + describe('AccessControl', () => { + it('guardian role', async () => { + this.guardianRole = web3.utils.soliditySha3('GUARDIAN_ROLE'); + this.managerRole = web3.utils.soliditySha3('POOLMANAGER_ROLE'); + this.guardianError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.guardianRole}`; + this.managerError = `AccessControl: account ${user.toLowerCase()} is missing role ${this.managerRole}`; + + expect(await this.strategy.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), guardian)).to.be.equal(true); + expect(await this.strategy.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), governor)).to.be.equal(true); + }); + it('manager role', async () => { + expect( + await this.strategy.hasRole(web3.utils.soliditySha3('POOLMANAGER_ROLE'), this.managerETH.address), + ).to.be.equal(true); + }); + it('withdraw - reverts nonManager', async () => { + await expectRevert(this.strategy.withdraw(BASE, { from: user }), this.managerError); + }); + it('addGuardian - reverts nonManager', async () => { + await expectRevert(this.strategy.addGuardian(this.wETH.address, { from: user }), this.managerError); + }); + it('revokeGuardian - reverts nonManager', async () => { + await expectRevert(this.strategy.revokeGuardian(this.wETH.address, { from: user }), this.managerError); + }); + it('setEmergencyExit - reverts nonManager', async () => { + await expectRevert(this.strategy.setEmergencyExit({ from: user }), this.managerError); + }); + it('setRewards - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setRewards(this.wETH.address, { from: user }), this.guardianError); + }); + it('setRewardAmount - reverts nonGuardian', async () => { + await expectRevert( + this.strategy.setRewardAmountAndMinimumAmountMoved(BASE, BASE, { from: user }), + this.guardianError, + ); + }); + it('setMinReportDelay - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setMinReportDelay(BASE, { from: user }), this.guardianError); + }); + it('setMaxReportDelay - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setMaxReportDelay(BASE, { from: user }), this.guardianError); + }); + it('setDebtThreshold - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setDebtThreshold(BASE, { from: user }), this.guardianError); + }); + it('sweep - reverts nonGuardian', async () => { + await expectRevert(this.strategy.sweep(this.wETH.address, user, { from: user }), this.guardianError); + }); + it('updateReferral - reverts nonGuardian', async () => { + await expectRevert(this.strategy.updateReferral(this.wETH.address, { from: user }), this.guardianError); + }); + it('updateMaxSingleTrade - reverts nonGuardian', async () => { + await expectRevert(this.strategy.updateMaxSingleTrade(new BN('0'), { from: user }), this.guardianError); + }); + it('setApr - reverts nonGuardian', async () => { + await expectRevert(this.strategy.setApr(new BN('0'), { from: user }), this.guardianError); + }); + it('updateSlippageProtectionOut - reverts nonGuardian', async () => { + await expectRevert(this.strategy.updateSlippageProtectionOut(new BN('0'), { from: user }), this.guardianError); + }); + it('invest - reverts nonGuardian', async () => { + await expectRevert(this.strategy.invest(new BN('0'), { from: user }), this.guardianError); + }); + it('rescueStuckEth - reverts nonGuardian', async () => { + await expectRevert(this.strategy.rescueStuckEth({ from: user }), this.guardianError); + }); + }); + }); + + describe('debtRatio', () => { + it('success - set correctly for strategy', async () => { + const debtRatio = (await this.managerETH.strategies(this.strategy.address)).debtRatio; + expect(debtRatio).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('8')).div(new BN('10'))); + }); + it('success - set correctly for manager', async () => { + expect(await this.managerETH.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('8')).div(new BN('10'))); + }); + }); + + describe('setGuardian - when there is a strategy', () => { + it('success - adding a new guardian', async () => { + await this.core.setGuardian(tester, { from: governor }); + expect(await this.managerETH.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), tester)).to.be.equal(true); + expect(await this.managerETH.hasRole(web3.utils.soliditySha3('GUARDIAN_ROLE'), guardian)).to.be.equal(false); + }); + it('success - resetting guardian', async () => { + await this.core.setGuardian(guardian, { from: governor }); + }); + }); + + describe('estimatedAPR', () => { + it('success - returns 0 when no asset', async () => { + expect(await this.strategy.estimatedAPR()).to.be.bignumber.equal(new BN('0')); + }); + }); + + describe('initializing contracts', () => { + it('success - send ETH and wETH to curve', async () => { + await this.owner.sendTransaction({ + to: this.curve.address, + value: ethers.utils.parseEther('10'), + }); + await this.owner.sendTransaction({ + to: this.wETH.address, + value: ethers.utils.parseEther('10'), + }); + await this.stETH.mint(this.curve.address, BASE.mul(new BN('10'))); + }); + }); + describe('harvest', () => { + it('init - minting on poolManager', async () => { + await this.wETH.mint(this.managerETH.address, ether('10')); + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(BASE.mul(new BN('10'))); + }); + + it('success - lent assets updated', async () => { + const balance2 = await balance.current(this.curve.address); + await this.strategy.harvest(); + // Still 10 total assets + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // But 8 lent from manager to strategy + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('2')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + // These 8 are then given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('8')); + expect(await this.strategy.wantBalance()).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.stethBalance()).to.be.bignumber.equal(ether('8')); + expect(await this.managerETH.totalDebt()).to.be.bignumber.equal(ether('8')); + expect((await this.managerETH.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('8'), + ); + expect(await balance.current(this.curve.address)).to.be.bignumber.equal(balance2.add(ether('8'))); + }); + + it('setting - creation of debt for the strategy', async () => { + await this.managerETH.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('5')).div(new BN('10')), + { from: governor }, + ); + expect((await this.managerETH.strategies(this.strategy.address)).debtRatio).to.be.bignumber.equal( + BASE_PARAMS.mul(new BN('5')).div(new BN('10')), + ); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + }); + it('success - manager debt ratio check', async () => { + expect(await this.managerETH.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('5')).div(new BN('10'))); + }); + + it('updateStrategyDebtRatio reverts', async () => { + await expectRevert( + this.managerETH.updateStrategyDebtRatio(tester, BASE_PARAMS.mul(new BN('5')).div(new BN('10')), { + from: governor, + }), + '78', + ); + await expectRevert( + this.managerETH.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('11')).div(new BN('10')), + { from: governor }, + ), + '76', + ); + }); + it('success - harvesting with debt', async () => { + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('5')); + + // Still 10 total assets + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('5')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('5')); + }); + it('success - resetting everything', async () => { + await this.managerETH.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('0')).div(new BN('10')), + { from: governor }, + ); + expect((await this.managerETH.strategies(this.strategy.address)).debtRatio).to.be.bignumber.equal( + BASE_PARAMS.mul(new BN('0')).div(new BN('10')), + ); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + expect(await this.managerETH.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('0')).div(new BN('10'))); + await this.strategy.harvest(); + // 3 have been withdrawn from strat + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('10')); + + // Still 10 total assets + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('0')); + }); + it('success - increasing back again debt ratios and setting dy', async () => { + await this.managerETH.updateStrategyDebtRatio( + this.strategy.address, + BASE_PARAMS.mul(new BN('8')).div(new BN('10')), + { from: governor }, + ); + // In this situation, we should use the Lido way + await this.curve.setDy(BASE.mul(new BN('9')).div(new BN('10'))); + }); + it('success - harvest using the Lido circuit', async () => { + const balance2 = await balance.current(this.curve.address); + await this.strategy.harvest(); + // Still 10 total assets + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // But 8 lent from manager to strategy + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('2')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + // These 8 are then given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('8')); + expect(await this.managerETH.totalDebt()).to.be.bignumber.equal(ether('8')); + expect((await this.managerETH.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('8'), + ); + // The amount of ETH on Curve should not have changed in this situation + expect(await balance.current(this.curve.address)).to.be.bignumber.equal(balance2); + // Setting reward back to normal + await this.curve.setDy(BASE); + }); + it('success - recording a gain', async () => { + // Minting two stETH meaning there is an increase + await this.stETH.mint(this.strategy.address, ether('2')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('10')); + }); + it('success - harvesting after a gain', async () => { + // There is 12 in total assets now, 0.8 * 12 should go to the strategy, the rest to the poolManager + await this.strategy.harvest(); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('12')); + // But 8 lent from manager to strategy + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('2.4')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('9.6')); + // These 8 are then given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('9.6')); + expect(await this.managerETH.totalDebt()).to.be.bignumber.equal(ether('9.6')); + expect((await this.managerETH.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('9.6'), + ); + }); + it('success - recording a loss', async () => { + await this.stETH.burn(this.strategy.address, ether('2')); + await this.strategy.harvest(); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + expect(await this.managerETH.debtRatio()).to.be.bignumber.equal(BASE_PARAMS.mul(new BN('8')).div(new BN('10'))); + // Still 10 total assets + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('8')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8')); + }); + }); + describe('withdraw', () => { + it('reverts - invalid strategy', async () => { + await expectRevert(this.managerETH.withdrawFromStrategy(governor, ether('1'), { from: governor }), '78'); + }); + it('success - wantBal < _amountNeeded', async () => { + await this.managerETH.withdrawFromStrategy(this.strategy.address, ether('1'), { from: governor }); + // 1 have been withdrawn from strat + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('3')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('7')); + // Still 10 total assets + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // 4 are given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + }); + it('success - wantBal >= amountNeeded', async () => { + await this.wETH.mint(this.strategy.address, ether('1')); + await this.managerETH.withdrawFromStrategy(this.strategy.address, ether('1'), { from: governor }); + // 1 have been withdrawn from strat + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('4')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('7')); + // Still 10 total assets + // total debt is not updated after withdrawing + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('10')); + // 4 are given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + }); + it('success - with a loss', async () => { + await this.curve.setDy(BASE.mul(new BN('11')).div(new BN('10'))); + // In this case you loose a portion and cannot withdraw everything + await this.managerETH.withdrawFromStrategy(this.strategy.address, ether('1'), { from: governor }); + + // 1 have been withdrawn from strat + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal( + ether('4').add(ether('1').mul(new BN('10')).div(new BN('11'))), + ); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('6')); + // Still 10 total assets + + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal( + ether('9').add(ether('10').div(new BN('11'))), + ); + // 4 are given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + await this.curve.setDy(BASE); + }); + }); + describe('liquidateAllPositions', () => { + it('success - setEmergencyExit', async () => { + await this.managerETH.setStrategyEmergencyExit(this.strategy.address, { from: governor }); + expect(await this.strategy.emergencyExit()).to.be.equal(true); + }); + it('success - harvest', async () => { + await this.strategy.harvest(); + // This harvest makes us find about the wETH that had been left aside + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal( + ether('10').add(ether('10').div(new BN('11'))), + ); + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('0')); + }); + }); + + describe('updateReferral', () => { + it('success', async () => { + await this.strategy.updateReferral(user, { from: governor }); + }); + }); + describe('updateMaxSingleTrade', () => { + it('success', async () => { + await this.strategy.updateMaxSingleTrade(BASE.mul(new BN('100')), { from: governor }); + expect(await this.strategy.maxSingleTrade()).to.be.bignumber.equal(BASE.mul(new BN('100'))); + }); + }); + describe('setApr', () => { + it('success', async () => { + await this.strategy.setApr(BASE.mul(new BN('9')).div(new BN('100')), { from: governor }); + expect(await this.strategy.apr()).to.be.bignumber.equal(BASE.mul(new BN('9')).div(new BN('100'))); + }); + }); + describe('updateSlippageProtectionOut', () => { + it('success', async () => { + await this.strategy.updateSlippageProtectionOut(new BN('51'), { from: governor }); + expect(await this.strategy.slippageProtectionOut()).to.be.bignumber.equal(new BN('51')); + }); + }); + describe('invest', () => { + it('reverts - wantBalance <= amount', async () => { + await expectRevert.unspecified(this.strategy.invest(BASE.mul(new BN('100')), { from: guardian })); + }); + + it('success', async () => { + // First minting wETH to have a non + await this.curve.setDy(BASE); + await this.wETH.mint(this.strategy.address, BASE.mul(new BN('1'))); + const stETHBalance = await this.strategy.stethBalance(); + await this.strategy.invest(BASE.mul(new BN('1')), { from: guardian }); + expect(await this.strategy.stethBalance()).to.be.bignumber.equal(stETHBalance.add(BASE.mul(new BN('1')))); + }); + }); + describe('rescueStuckEth', () => { + it('success - eth converted', async () => { + await this.owner.sendTransaction({ + to: this.strategy.address, + value: ethers.utils.parseEther('10'), + }); + await this.strategy.rescueStuckEth({ from: guardian }); + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(BASE.mul(new BN('10'))); + }); + }); + describe('sweep', () => { + it('reverts - wETH', async () => { + await expectRevert(this.strategy.sweep(this.wETH.address, governor, { from: guardian }), '93'); + }); + it('reverts - stETH', async () => { + await expectRevert(this.strategy.sweep(this.stETH.address, governor, { from: guardian }), '93'); + }); + }); + describe('harvest - other cases', () => { + it('init', async () => { + [this.core, this.ANGLE, this.stableMaster, this.agEUR] = await initAngle(governor, guardian); + [ + this.wETH, + this.oracleETH, + this.managerETH, + this.sanETH_EUR, + this.perpetualManagerETH, + this.feeManagerETH, + this.stETH, + this.curve, + this.strategy, + ] = await initWETH(this.stableMaster, this.ANGLE, governor, guardian); + await this.owner.sendTransaction({ + to: this.curve.address, + value: ethers.utils.parseEther('10'), + }); + await this.owner.sendTransaction({ + to: this.wETH.address, + value: ethers.utils.parseEther('10'), + }); + await this.stETH.mint(this.curve.address, BASE.mul(new BN('10'))); + await this.wETH.mint(this.managerETH.address, ether('10')); + await this.strategy.harvest(); + }); + it('success - withdraw < withdrawn', async () => { + // In this situation we should have a profit inferior to the loss + // This will result in a loss if we increase the dy + await this.curve.setDy(BASE.mul(new BN('20')).div(new BN('10'))); + await this.wETH.burn(this.managerETH.address, ether('2')); + await this.strategy.harvest(); + // Has lost 2, then to bring it back to 0.64 => has lost 0.8 when withdrawing + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('7.2')); + // But 8 lent from manager to strategy + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('0.8')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('6.4')); + // These 8 are then given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('6.4')); + expect(await this.strategy.wantBalance()).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.stethBalance()).to.be.bignumber.equal(ether('6.4')); + expect(await this.managerETH.totalDebt()).to.be.bignumber.equal(ether('6.4')); + expect((await this.managerETH.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('6.4'), + ); + await this.curve.setDy(BASE); + }); + it('success - wantBal < toWithdraw', async () => { + await this.stETH.mint(this.strategy.address, ether('2')); + await this.strategy.updateMaxSingleTrade(new BN('0'), { from: guardian }); + await this.strategy.harvest(); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(ether('7.2')); + // But 8 lent from manager to strategy + expect(await this.wETH.balanceOf(this.managerETH.address)).to.be.bignumber.equal(ether('0.8')); + expect(await this.strategy.estimatedTotalAssets()).to.be.bignumber.equal(ether('8.4')); + // These 8 are then given to the lender + expect(await this.wETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('0')); + expect(await this.stETH.balanceOf(this.strategy.address)).to.be.bignumber.equal(ether('8.4')); + expect(await this.strategy.wantBalance()).to.be.bignumber.equal(ether('0')); + expect(await this.strategy.stethBalance()).to.be.bignumber.equal(ether('8.4')); + expect(await this.managerETH.totalDebt()).to.be.bignumber.equal(ether('6.4')); + expect((await this.managerETH.strategies(this.strategy.address)).totalStrategyDebt).to.be.bignumber.equal( + ether('6.4'), + ); + }); + it('success - harvestTrigger with a big debt threshold', async () => { + await this.strategy.setDebtThreshold(ether('1'), { from: guardian }); + await this.strategy.setMinReportDelay(new BN('0'), { from: guardian }); + await this.strategy.harvest(); + await this.stETH.burn(this.strategy.address, ether('8.4')); + expect(await this.strategy.harvestTrigger()).to.be.equal(true); + }); + it('success - strategyExit with too much freed', async () => { + await this.managerETH.setStrategyEmergencyExit(this.strategy.address, { from: governor }); + expect(await this.strategy.emergencyExit()).to.be.equal(true); + const assets = await this.managerETH.getTotalAsset(); + await this.wETH.mint(this.strategy.address, BASE.mul(new BN('100'))); + await this.strategy.harvest(); + expect(await this.managerETH.getTotalAsset()).to.be.bignumber.equal(assets.add(BASE.mul(new BN('100')))); + }); + }); +}); diff --git a/test/typeScript/helpers.ts b/test/typeScript/helpers.ts new file mode 100644 index 0000000..aeb9a92 --- /dev/null +++ b/test/typeScript/helpers.ts @@ -0,0 +1,284 @@ +import { ethers } from 'hardhat'; +import { BigNumber, Contract } from 'ethers'; +import { parseAmount, multBy10e15 } from '../../utils/bignumber'; + +import { + AgToken, + Core, + PoolManager, + FeeManager, + MockANGLE, + MockOracle, + MockToken, + PerpetualManagerFront, + SanToken, + StableMasterFront, +} from '../../typechain'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signers'; + +export const BASE = parseAmount.ether(1); +export const BASE_PARAMS = parseAmount.gwei(1); +export const BASE_15 = multBy10e15(15); +export const BASE_RATE = BigNumber.from(10 ** 2); +export const BASE_ORACLE = parseAmount.ether(1); + +export const MAX_MINT_AMOUNT = BigNumber.from(2).pow(BigNumber.from(256)).sub(BigNumber.from(1)); + +export async function setupUsers( + addresses: string[], + contracts: T, +): Promise<({ address: string } & T)[]> { + const users: ({ address: string } & T)[] = []; + for (const address of addresses) { + users.push(await setupUser(address, contracts)); + } + return users; +} + +export async function setupUser( + address: string, + contracts: T, +): Promise<{ address: string } & T> { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const user: any = { address }; + for (const key of Object.keys(contracts)) { + user[key] = contracts[key].connect(await ethers.getSigner(address)); + } + return user as { address: string } & T; +} + +export async function initAngle( + governor: SignerWithAddress, + guardian: SignerWithAddress, +): Promise<{ core: Core; ANGLE: MockANGLE; stableMaster: StableMasterFront; agToken: AgToken }> { + const CoreArtifacts = await ethers.getContractFactory('Core'); + const MockANGLEArtifacts = await ethers.getContractFactory('MockANGLE'); + const AgTokenArtifacts = await ethers.getContractFactory('AgToken'); + const StableMasterArtifacts = await ethers.getContractFactory('StableMasterFront'); + + const core = (await CoreArtifacts.deploy(governor.address, guardian.address)) as Core; + const ANGLE = (await MockANGLEArtifacts.deploy('ANGLE', 'ANGLE')) as MockANGLE; + const stableMaster = (await StableMasterArtifacts.deploy()) as StableMasterFront; + await stableMaster.initialize(core.address); + const agToken = (await AgTokenArtifacts.deploy()) as AgToken; + await agToken.initialize('agEUR', 'agEUR', stableMaster.address); + + await (await core.connect(governor).deployStableMaster(agToken.address)).wait(); + + return { core, ANGLE, stableMaster, agToken }; +} + +export async function initCollateral( + name: string, + stableMaster: StableMasterFront, + ANGLE: MockANGLE, + governor: SignerWithAddress, + collatBase = BigNumber.from('18'), + initFees = true, +): Promise<{ + token: MockToken; + oracle: MockOracle; + manager: PoolManager; + sanToken: SanToken; + perpetualManager: PerpetualManagerFront; + feeManager: FeeManager; +}> { + const SanTokenArtifacts = await ethers.getContractFactory('SanToken'); + const PoolManagerArtifacts = await ethers.getContractFactory('PoolManager'); + const PerpetualManagerArtifacts = await ethers.getContractFactory('PerpetualManagerFront'); + const FeeManagerArtifacts = await ethers.getContractFactory('FeeManager'); + const MockOracleArtifacts = await ethers.getContractFactory('MockOracle'); + const MockTokenArtifacts = await ethers.getContractFactory('MockToken'); + + const token = (await MockTokenArtifacts.deploy(name, name, collatBase)) as MockToken; + const oracle = (await MockOracleArtifacts.deploy(BASE_ORACLE, collatBase)) as MockOracle; + const manager = (await PoolManagerArtifacts.deploy()) as PoolManager; + + await manager.initialize(token.address, stableMaster.address); + const sanName = ethers.utils.formatBytes32String('san' + name); + const sanToken = (await SanTokenArtifacts.deploy()) as SanToken; + await sanToken.initialize(sanName, sanName, manager.address); + const perpetualManager = (await PerpetualManagerArtifacts.deploy()) as PerpetualManagerFront; + await perpetualManager.initialize(manager.address, ANGLE.address); + const feeManager = (await FeeManagerArtifacts.deploy(manager.address)) as FeeManager; + + await ( + await stableMaster + .connect(governor) + .deployCollateral(manager.address, perpetualManager.address, feeManager.address, oracle.address, sanToken.address) + ).wait(); + + if (initFees) { + // for test purpose + const xFeeMint = [parseAmount.gwei(0), parseAmount.gwei(1)]; + const yFeeMint = [parseAmount.gwei(0.1), parseAmount.gwei(0.1)]; + await stableMaster.connect(governor).setUserFees(manager.address, xFeeMint, yFeeMint, 1); + + const xFeeBurn = [parseAmount.gwei(0), parseAmount.gwei(1)]; + const yFeeBurn = [parseAmount.gwei(0.1), parseAmount.gwei(0.1)]; + await stableMaster.connect(governor).setUserFees(manager.address, xFeeBurn, yFeeBurn, 0); + + const xHAFeesDeposit = [parseAmount.gwei(0.1), parseAmount.gwei(0.4), parseAmount.gwei(0.7)]; + const yHAFeesDeposit = [parseAmount.gwei(0.01), parseAmount.gwei(0.01), parseAmount.gwei(0.01)]; + await perpetualManager.connect(governor).setHAFees(xHAFeesDeposit, yHAFeesDeposit, 1); + + const xHAFeesWithdraw = [parseAmount.gwei(0.1), parseAmount.gwei(0.4), parseAmount.gwei(0.7)]; + const yHAFeesWithdraw = [parseAmount.gwei(0.01), parseAmount.gwei(0.01), parseAmount.gwei(0.01)]; + await perpetualManager.connect(governor).setHAFees(xHAFeesWithdraw, yHAFeesWithdraw, 0); + + const xSlippage = [parseAmount.gwei(1), parseAmount.gwei(1.5)]; + const ySlippage = [parseAmount.gwei(1), parseAmount.gwei(0)]; + const xSlippageFee = [parseAmount.gwei(1), parseAmount.gwei(1.5)]; + const ySlippageFee = [parseAmount.gwei(1), parseAmount.gwei(0)]; + + await feeManager.connect(governor).setFees(xSlippage, ySlippage, 3); + await feeManager.connect(governor).setFees(xSlippageFee, ySlippageFee, 0); + } else { + const xFeeMint = [parseAmount.gwei('0'), parseAmount.gwei('0.4'), parseAmount.gwei('0.7'), parseAmount.gwei('1')]; + const yFeeMint = [ + parseAmount.gwei('0.08'), + parseAmount.gwei('0.025'), + parseAmount.gwei('0.005'), + parseAmount.gwei('0.002'), + ]; + await stableMaster.connect(governor).setUserFees(manager.address, xFeeMint, yFeeMint, 1); + + const xFeeBurn = [parseAmount.gwei('0'), parseAmount.gwei('0.3'), parseAmount.gwei('0.6'), parseAmount.gwei('1')]; + const yFeeBurn = [ + parseAmount.gwei('0.002'), + parseAmount.gwei('0.003'), + parseAmount.gwei('0.005'), + parseAmount.gwei('0.015'), + ]; + await stableMaster.connect(governor).setUserFees(manager.address, xFeeBurn, yFeeBurn, 0); + + const xHAFeesDeposit = [ + parseAmount.gwei('0'), + parseAmount.gwei('0.4'), + parseAmount.gwei('0.7'), + parseAmount.gwei('1'), + ]; + const yHAFeesDeposit = [ + parseAmount.gwei('0.002'), + parseAmount.gwei('0.005'), + parseAmount.gwei('0.01'), + parseAmount.gwei('0.03'), + ]; + await perpetualManager.connect(governor).setHAFees(xHAFeesDeposit, yHAFeesDeposit, 1); + + const xHAFeesWithdraw = [ + parseAmount.gwei('0'), + parseAmount.gwei('0.4'), + parseAmount.gwei('0.7'), + parseAmount.gwei('1'), + ]; + const yHAFeesWithdraw = [ + parseAmount.gwei('0.06'), + parseAmount.gwei('0.02'), + parseAmount.gwei('0.01'), + parseAmount.gwei('0.002'), + ]; + await perpetualManager.connect(governor).setHAFees(xHAFeesWithdraw, yHAFeesWithdraw, 0); + + const xSlippage = [ + parseAmount.gwei('0.5'), + parseAmount.gwei('1'), + parseAmount.gwei('1.2'), + parseAmount.gwei('1.5'), + ]; + const ySlippage = [ + parseAmount.gwei('0.5'), + parseAmount.gwei('0.2'), + parseAmount.gwei('0.1'), + parseAmount.gwei('0'), + ]; + const xSlippageFee = [ + parseAmount.gwei('0.5'), + parseAmount.gwei('1'), + parseAmount.gwei('1.2'), + parseAmount.gwei('1.5'), + ]; + const ySlippageFee = [ + parseAmount.gwei('0.75'), + parseAmount.gwei('0.5'), + parseAmount.gwei('0.15'), + parseAmount.gwei('0'), + ]; + + await feeManager.connect(governor).setFees(xSlippage, ySlippage, 3); + await feeManager.connect(governor).setFees(xSlippageFee, ySlippageFee, 0); + } + + const xBonusMalusMint = [parseAmount.gwei('0.5'), parseAmount.gwei('1')]; + const yBonusMalusMint = [parseAmount.gwei('0.8'), parseAmount.gwei('1')]; + const xBonusMalusBurn = [ + parseAmount.gwei('0'), + parseAmount.gwei('0.5'), + parseAmount.gwei('1'), + parseAmount.gwei('1.3'), + parseAmount.gwei('1.5'), + ]; + const yBonusMalusBurn = [ + parseAmount.gwei('10'), + parseAmount.gwei('4'), + parseAmount.gwei('1.5'), + parseAmount.gwei('1'), + parseAmount.gwei('1'), + ]; + await feeManager.connect(governor).setFees(xBonusMalusMint, yBonusMalusMint, 1); + await feeManager.connect(governor).setFees(xBonusMalusBurn, yBonusMalusBurn, 2); + await feeManager.connect(governor).setHAFees(parseAmount.gwei('1'), parseAmount.gwei('1')); + + await stableMaster + .connect(governor) + .setIncentivesForSLPs(parseAmount.gwei('0.5'), parseAmount.gwei('0.5'), manager.address); + await stableMaster + .connect(governor) + .setCapOnStableAndMaxInterests( + parseAmount.ether('1000000000000'), + parseAmount.ether('1000000000000'), + manager.address, + ); + + // Limit HA hedge should always be set before the target HA hedge + await perpetualManager.connect(governor).setTargetAndLimitHAHedge(parseAmount.gwei('0.9'), parseAmount.gwei('0.95')); + await perpetualManager.connect(governor).setBoundsPerpetual(parseAmount.gwei('3'), parseAmount.gwei('0.0625')); + await perpetualManager.connect(governor).setKeeperFeesLiquidationRatio(parseAmount.gwei('0.2')); + await perpetualManager.connect(governor).setKeeperFeesCap(parseAmount.ether('100'), parseAmount.ether('100')); + const xKeeperFeesClosing = [parseAmount.gwei('0.25'), parseAmount.gwei('0.5'), parseAmount.gwei('1')]; + const yKeeperFeesClosing = [parseAmount.gwei('0.1'), parseAmount.gwei('0.6'), parseAmount.gwei('1')]; + await perpetualManager.connect(governor).setKeeperFeesClosing(xKeeperFeesClosing, yKeeperFeesClosing); + + await feeManager.connect(governor).updateUsersSLP(); + await feeManager.connect(governor).updateHA(); + + await stableMaster + .connect(governor) + .unpause('0xfb286912c6eadba541f23a3bb3e83373ab139b6e65d84e2a473c186efc2b4642', manager.address); + await stableMaster + .connect(governor) + .unpause('0xe0136b3661826a483734248681e4f59ae66bc6065ceb43fdd469ecb22c21d745', manager.address); + await perpetualManager.connect(governor).unpause(); + + return { token, oracle, manager, sanToken, perpetualManager, feeManager }; +} + +export function piecewiseFunction(value: BigNumber, xArray: BigNumber[], yArray: BigNumber[]): BigNumber { + if (value.gte(xArray[xArray.length - 1])) return yArray[yArray.length - 1]; + if (value.lte(xArray[0])) return yArray[0]; + + let i = 0; + while (value.gte(xArray[i + 1])) { + i += 1; + } + const pct = value + .sub(xArray[i]) + .mul(BASE) + .div(xArray[i + 1].sub(xArray[i])); + const normalized = pct + .mul(yArray[i + 1].sub(yArray[i])) + .div(BASE) + .add(yArray[i]); + + return normalized; +} diff --git a/test/typeScript/testBase.ts b/test/typeScript/testBase.ts new file mode 100644 index 0000000..2bed5e3 --- /dev/null +++ b/test/typeScript/testBase.ts @@ -0,0 +1,255 @@ +import { ethers, expect } from 'hardhat'; +import { BigNumber } from 'ethers'; +import { parseAmount, gwei, mwei } from '../../utils/bignumber'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signers'; + +// we import our utilities + +import { + PoolManager, + StableMasterFront, + MockToken, + MockANGLE, + SanToken, + AgToken, + PerpetualManagerFront, +} from '../../typechain'; + +import { + // functions + initAngle, + initCollateral, +} from './helpers'; + +let ANGLE: MockANGLE; +let stableMasterEUR: StableMasterFront; +let agEUR: AgToken; + +let wBTC: MockToken; +let managerBTC: PoolManager; +let sanTokenBTC: SanToken; +let perpEURBTC: PerpetualManagerFront; + +let DAI: MockToken; +let managerDAI: PoolManager; +let sanTokenDAI: SanToken; +let perpEURDAI: PerpetualManagerFront; + +let deployer: SignerWithAddress; +let guardian: SignerWithAddress; +let user: SignerWithAddress; +let ha: SignerWithAddress; + +describe('Testing collateral with different bases ', function () { + describe('Users, HAs and SLPs', function () { + before(async function () { + ({ deployer, guardian, user, ha } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + manager: managerBTC, + sanToken: sanTokenBTC, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(9), true)); + + ({ + token: DAI, + manager: managerDAI, + sanToken: sanTokenDAI, + perpetualManager: perpEURDAI, + } = await initCollateral('DAI', stableMasterEUR, ANGLE, deployer, BigNumber.from(6), true)); + + await wBTC.connect(user).mint(user.address, gwei(1000)); + await DAI.connect(user).mint(user.address, mwei(1000)); + await wBTC.connect(ha).mint(ha.address, gwei(1000)); + await DAI.connect(ha).mint(ha.address, mwei(1000)); + + await wBTC.connect(user).approve(stableMasterEUR.address, gwei(1000)); + await DAI.connect(user).approve(stableMasterEUR.address, mwei(1000)); + await wBTC.connect(ha).approve(stableMasterEUR.address, gwei(1000)); + await DAI.connect(ha).approve(stableMasterEUR.address, mwei(1000)); + + await wBTC.connect(user).approve(perpEURBTC.address, gwei(1000)); + await DAI.connect(user).approve(perpEURDAI.address, mwei(1000)); + await wBTC.connect(ha).approve(perpEURBTC.address, gwei(1000)); + await DAI.connect(ha).approve(perpEURDAI.address, mwei(1000)); + + this.countPerpBTC = BigNumber.from('0'); + this.countPerpDAI = BigNumber.from('0'); + }); + + it('mint success - correct balances', async function () { + await stableMasterEUR.connect(user).mint(gwei('1'), user.address, managerBTC.address, 0); + expect((await agEUR.balanceOf(user.address)).toString()).to.be.equal(parseAmount.ether('0.9').toString()); + + await stableMasterEUR.connect(user).mint(mwei('1'), user.address, managerDAI.address, 0); + expect((await agEUR.balanceOf(user.address)).toString()).to.be.equal(parseAmount.ether('1.8').toString()); + }); + + it('deposit success - correct balances', async function () { + await stableMasterEUR.connect(user).deposit(gwei('1'), user.address, managerBTC.address); + expect((await sanTokenBTC.balanceOf(user.address)).toString()).to.be.equal(gwei('1').toString()); + + await stableMasterEUR.connect(user).deposit(mwei('1'), user.address, managerDAI.address); + expect((await sanTokenDAI.balanceOf(user.address)).toString()).to.be.equal(mwei('1').toString()); + }); + + it('openPerpetual success - correct perpetual data BTC', async function () { + await perpEURBTC + .connect(ha) + .openPerpetual( + ha.address, + gwei('1'), + gwei('0.8'), + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ); + this.countPerpBTC = this.countPerpBTC.add(BigNumber.from('1')); + const perpBTC = await perpEURBTC.connect(ha).perpetualData(this.countPerpBTC); + this.netAmountBTC = gwei('1').sub(gwei('0.8').mul(BigNumber.from('1')).div(BigNumber.from('100'))); + expect(perpBTC.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpBTC.margin.toString()).to.be.equal(this.netAmountBTC.toString()); + expect(perpBTC.committedAmount.toString()).to.be.equal(gwei('0.8').toString()); + }); + it('success - correct balance HA BTC', async function () { + this.balanceHABTC = gwei(1000).sub(gwei(1)); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + + it('openPerpetual success - correct perpetual data DAI', async function () { + await perpEURDAI + .connect(ha) + .openPerpetual( + ha.address, + mwei('1'), + mwei('0.8'), + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ); + this.countPerpDAI = this.countPerpDAI.add(BigNumber.from('1')); + const perpDAI = await perpEURDAI.perpetualData(this.countPerpDAI); + this.netAmountDAI = mwei('1').sub(mwei('0.8').mul(BigNumber.from('1')).div(BigNumber.from('100'))); + expect(perpDAI.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpDAI.margin.toString()).to.be.equal(this.netAmountDAI.toString()); + expect(perpDAI.committedAmount.toString()).to.be.equal(mwei('0.8').toString()); + }); + + it('success - HAs - correct balance HA DAI', async function () { + this.balanceHADAI = mwei(1000).sub(mwei(1)); + expect((await DAI.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHADAI.toString()); + }); + + it('addToPerpetual - success BTC', async function () { + await perpEURBTC.connect(ha).addToPerpetual(this.countPerpBTC, gwei('1')); + const perpBTC = await perpEURBTC.connect(ha).perpetualData(this.countPerpBTC); + this.netAmountBTC = this.netAmountBTC.add(gwei('1')); + expect(perpBTC.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpBTC.margin.toString()).to.be.equal(this.netAmountBTC.toString()); + expect(perpBTC.committedAmount.toString()).to.be.equal(gwei('0.8').toString()); + }); + it('success - HAs - correct balance HA BTC', async function () { + this.balanceHABTC = this.balanceHABTC.sub(gwei(1)); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + + it('addToPerpetual success - HA DAI', async function () { + await perpEURDAI.connect(ha).addToPerpetual(this.countPerpDAI, mwei('1')); + const perpDAI = await perpEURDAI.connect(ha).perpetualData(this.countPerpDAI); + this.netAmountDAI = this.netAmountDAI.add(mwei('1')); + this.feesDAI = mwei('2').sub(this.netAmountDAI); + expect(perpDAI.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpDAI.margin.toString()).to.be.equal(this.netAmountDAI.toString()); + expect(perpDAI.committedAmount.toString()).to.be.equal(mwei('0.8').toString()); + }); + it('success - HAs - correct balance HA DAI', async function () { + this.balanceHADAI = this.balanceHADAI.sub(mwei(1)); + expect((await DAI.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHADAI.toString()); + }); + + it('removeFromPerpetual success - HA BTC', async function () { + await perpEURBTC.connect(ha).removeFromPerpetual(this.countPerpBTC, gwei('1'), ha.address); + const perpBTC = await perpEURBTC.connect(ha).perpetualData(this.countPerpBTC); + this.netAmountBTC = this.netAmountBTC.sub(gwei('1')); + expect(perpBTC.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpBTC.margin.toString()).to.be.equal(this.netAmountBTC.toString()); + expect(perpBTC.committedAmount.toString()).to.be.equal(gwei('0.8').toString()); + }); + + it('success - HAs - correct balance HA BTC', async function () { + this.balanceHABTC = this.balanceHABTC.add(gwei('1')); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + + it('removeFromPerpetual success - HA DAI', async function () { + await perpEURDAI.connect(ha).removeFromPerpetual(this.countPerpDAI, mwei('1'), ha.address); + const perpDAI = await perpEURDAI.connect(ha).perpetualData(this.countPerpDAI); + this.netAmountDAI = this.netAmountDAI.sub(mwei('1')); + this.feesDAI = this.feesDAI.add(mwei('1').div(BigNumber.from('100'))); + expect(perpDAI.entryRate.toString()).to.be.equal(parseAmount.ether('1').toString()); + expect(perpDAI.margin.toString()).to.be.equal(this.netAmountDAI.toString()); + expect(perpDAI.committedAmount.toString()).to.be.equal(mwei('0.8').toString()); + }); + it('success - correct balance HA DAI', async function () { + this.balanceHADAI = this.balanceHADAI.add(mwei(1)); + expect((await DAI.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHADAI.toString()); + }); + + it('closePerpetual success - HA BTC', async function () { + await perpEURBTC.connect(ha).closePerpetual(this.countPerpBTC, ha.address, parseAmount.ether('0')); + this.balanceHABTC = this.balanceHABTC.add( + this.netAmountBTC.sub(gwei('0.8').mul(BigNumber.from('1')).div(BigNumber.from('100'))), + ); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + + it('closePerpetual success - HA DAI', async function () { + await perpEURDAI.connect(ha).closePerpetual(this.countPerpDAI, ha.address, parseAmount.ether('0')); + this.balanceHADAI = this.balanceHADAI.add( + this.netAmountDAI.sub(mwei('0.8').mul(BigNumber.from('1')).div(BigNumber.from('100'))), + ); + expect((await DAI.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHADAI.toString()); + }); + + it('openPerpetual success - new perp BTC', async function () { + await perpEURBTC + .connect(ha) + .openPerpetual( + ha.address, + gwei('1'), + gwei('0.8'), + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ); + this.countPerpBTC = this.countPerpBTC.add(BigNumber.from('1')); + this.balanceHABTC = this.balanceHABTC.sub(gwei('1')); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + it('burn success - partially exit stable seeker', async function () { + await stableMasterEUR + .connect(user) + .burn(parseAmount.ether('0.5'), user.address, user.address, managerBTC.address, 0); + }); + it('forceClosePerpetuals success - perpetual cashed out', async function () { + await perpEURBTC.connect(guardian).forceClosePerpetuals([this.countPerpBTC]); + this.balanceHABTC = this.balanceHABTC + .add(gwei('1')) + .sub(gwei('0.8').mul(BigNumber.from('2')).div(BigNumber.from('100'))); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + + it('openPerpetual - new perp BTC', async function () { + await perpEURBTC + .connect(ha) + .openPerpetual( + ha.address, + gwei('1'), + gwei('0.3'), + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ); + this.countPerpBTC = this.countPerpBTC.add(BigNumber.from('1')); + this.balanceHABTC = this.balanceHABTC.sub(gwei('1')); + expect((await wBTC.balanceOf(ha.address)).toString()).to.be.equal(this.balanceHABTC.toString()); + }); + }); +}); diff --git a/test/typeScript/testFees.ts b/test/typeScript/testFees.ts new file mode 100644 index 0000000..42bd914 --- /dev/null +++ b/test/typeScript/testFees.ts @@ -0,0 +1,767 @@ +import { ethers, expect } from 'hardhat'; +import { BigNumber } from 'ethers'; +import { parseAmount } from '../../utils/bignumber'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signers'; +// we import our utilities + +import { + PoolManager, + StableMasterFront, + MockOracle, + FeeManager, + MockToken, + MockANGLE, + PerpetualManagerFront, + AgToken, +} from '../../typechain'; + +import { + BASE, + BASE_ORACLE, + BASE_PARAMS, + BASE_RATE, + // functions + initAngle, + initCollateral, + piecewiseFunction, +} from './helpers'; + +let maxAlock: BigNumber; + +let ANGLE: MockANGLE; +let stableMasterEUR: StableMasterFront; +let agEUR: AgToken; + +let wBTC: MockToken; +let oracleBTC: MockOracle; +let managerBTC: PoolManager; +let feeManagerContract: FeeManager; +let perpEURBTC: PerpetualManagerFront; + +let deployer: SignerWithAddress; +let guardian: SignerWithAddress; +let user: SignerWithAddress; +let ha: SignerWithAddress; +let slp: SignerWithAddress; + +let collatBASE: BigNumber; +const mintAmount = parseAmount.ether(100); +const burnAmount = parseAmount.ether(50).mul(BASE_RATE); +const commitAmount = parseAmount.ether(30); +const broughtAmount = parseAmount.ether(50); +const slpDeposit = parseAmount.ether(50); + +// WARNING if the deployed contract doesn't have the same fees please update this file +// hardcoded piecewise linear functions +const xFeeMint: BigNumber[] = [parseAmount.gwei(0), parseAmount.gwei(0.4), parseAmount.gwei(0.7), parseAmount.gwei(1)]; +const yFeeMint: BigNumber[] = [ + parseAmount.gwei(0.08), + parseAmount.gwei(0.025), + parseAmount.gwei(0.005), + parseAmount.gwei(0.002), +]; +const xFeeBurn: BigNumber[] = [parseAmount.gwei(0), parseAmount.gwei(0.3), parseAmount.gwei(0.6), parseAmount.gwei(1)]; +const yFeeBurn: BigNumber[] = [ + parseAmount.gwei(0.002), + parseAmount.gwei(0.003), + parseAmount.gwei(0.005), + parseAmount.gwei(0.015), +]; +// const feesForSLPs: BigNumber = parseAmount.gwei(0.5); + +const xBonusMalusMint: BigNumber[] = [parseAmount.gwei(0.5), parseAmount.gwei(1)]; +const yBonusMalusMint: BigNumber[] = [parseAmount.gwei(0.8), parseAmount.gwei(1)]; +const xBonusMalusBurn: BigNumber[] = [ + parseAmount.gwei(0), + parseAmount.gwei(0.5), + parseAmount.gwei(1), + parseAmount.gwei(1.3), + parseAmount.gwei(1.5), +]; +const yBonusMalusBurn: BigNumber[] = [ + parseAmount.gwei(10), + parseAmount.gwei(4), + parseAmount.gwei(1.5), + parseAmount.gwei(1), + parseAmount.gwei(1), +]; + +const xSlippage: BigNumber[] = [ + parseAmount.gwei(0.5), + parseAmount.gwei(1), + parseAmount.gwei(1.2), + parseAmount.gwei(1.5), +]; +const ySlippage: BigNumber[] = [ + parseAmount.gwei(0.5), + parseAmount.gwei(0.2), + parseAmount.gwei(0.1), + parseAmount.gwei(0), +]; + +const xSlippageFee: BigNumber[] = [ + parseAmount.gwei(0.5), + parseAmount.gwei(1), + parseAmount.gwei(1.2), + parseAmount.gwei(1.5), +]; +const ySlippageFee: BigNumber[] = [ + parseAmount.gwei(0.75), + parseAmount.gwei(0.5), + parseAmount.gwei(0.15), + parseAmount.gwei(0), +]; + +const xHAFeesDeposit: BigNumber[] = [ + parseAmount.gwei(0), + parseAmount.gwei(0.4), + parseAmount.gwei(0.7), + parseAmount.gwei(1), +]; +const yHAFeesDeposit: BigNumber[] = [ + parseAmount.gwei(0.002), + parseAmount.gwei(0.005), + parseAmount.gwei(0.01), + parseAmount.gwei(0.03), +]; +const xHAFeesWithdraw: BigNumber[] = [ + parseAmount.gwei(0), + parseAmount.gwei(0.4), + parseAmount.gwei(0.7), + parseAmount.gwei(1), +]; +const yHAFeesWithdraw: BigNumber[] = [ + parseAmount.gwei(0.06), + parseAmount.gwei(0.02), + parseAmount.gwei(0.01), + parseAmount.gwei(0.002), +]; + +describe('KeeperFees update - FeeManager', function () { + describe('Only Stable seekers', function () { + let PoolManagerStockInStable = BigNumber.from(0); + let stableOut = BigNumber.from(0); + + before(async function () { + ({ deployer, guardian, user } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + oracle: oracleBTC, + manager: managerBTC, + feeManager: feeManagerContract, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(18), false)); + collatBASE = BigNumber.from(10).pow(BigNumber.from(18)); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + await wBTC.connect(user).mint(user.address, parseAmount.ether(1000)); + + await wBTC.connect(user).approve(stableMasterEUR.address, parseAmount.ether(1000)); + }); + it('success - after minting', async () => { + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + stableOut = mintAmount.mul(BigNumber.from(92)).div(BigNumber.from(100)); + PoolManagerStockInStable = mintAmount; + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - after oracle divided by 2', async () => { + const divisionOracle = BigNumber.from('2'); + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE).div(divisionOracle))).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.div(divisionOracle); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + // await printFees(stableMasterEUR, managerBTC); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + }); + + describe('Stable seekers & HA', function () { + let PoolManagerStockInStable = BigNumber.from(0); + let stableOut = BigNumber.from(0); + + before(async function () { + ({ deployer, guardian, user } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + oracle: oracleBTC, + manager: managerBTC, + feeManager: feeManagerContract, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(18), false)); + collatBASE = BigNumber.from(10).pow(BigNumber.from(18)); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + await wBTC.connect(user).mint(user.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(stableMasterEUR.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(perpEURBTC.address, parseAmount.ether(1000)); + }); + it('success - after minting', async () => { + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + stableOut = mintAmount.mul(BigNumber.from(92)).div(BigNumber.from(100)); + PoolManagerStockInStable = mintAmount; + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - after covering a tenth by a tenth', async () => { + await ( + await perpEURBTC + .connect(user) + .openPerpetual( + user.address, + broughtAmount, + commitAmount, + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ) + ).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.add(broughtAmount); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - after covering 2 tenth by 2 tenth', async () => { + await ( + await perpEURBTC + .connect(user) + .openPerpetual( + user.address, + broughtAmount, + commitAmount, + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ) + ).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.add(broughtAmount); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + // await printFees(stableMasterEUR, managerBTC); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - after oracle divided by 5', async () => { + const divisionOracle = BigNumber.from('5'); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE).div(divisionOracle))).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.div(divisionOracle); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + // await printFees(stableMasterEUR, managerBTC); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - HAs are exiting', async () => { + await (await perpEURBTC.connect(user).closePerpetual(1, user.address, parseAmount.ether('0'))).wait(); + await (await perpEURBTC.connect(user).closePerpetual(2, user.address, parseAmount.ether('0'))).wait(); + + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - after oracle back to normal', async () => { + const divisionOracle = BigNumber.from('5'); + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.mul(divisionOracle); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + }); + + describe('Stable seekers, HA & SLP', function () { + let PoolManagerStockInStable = BigNumber.from(0); + let stableOut = BigNumber.from(0); + + before(async function () { + ({ deployer, guardian, user } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + oracle: oracleBTC, + manager: managerBTC, + feeManager: feeManagerContract, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(18), false)); + collatBASE = BigNumber.from(10).pow(BigNumber.from(18)); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + await wBTC.connect(user).mint(user.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(stableMasterEUR.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(perpEURBTC.address, parseAmount.ether(1000)); + }); + + it('success - after minting and cover', async () => { + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + await ( + await perpEURBTC + .connect(user) + .openPerpetual( + user.address, + broughtAmount, + commitAmount, + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ) + ).wait(); + + stableOut = mintAmount.mul(BigNumber.from(92)).div(BigNumber.from(100)); + PoolManagerStockInStable = mintAmount; + PoolManagerStockInStable = PoolManagerStockInStable.add(broughtAmount); + + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + + // await printFees(stableMasterEUR, managerBTC); + }); + + it('success - after SLP enters with half BASE', async () => { + await (await stableMasterEUR.connect(user).deposit(slpDeposit, user.address, managerBTC.address)).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.add(slpDeposit); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + // await printFees(stableMasterEUR, managerBTC); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - oracle divided by 3', async () => { + const divisionOracle = BigNumber.from('3'); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE).div(divisionOracle))).wait(); + + PoolManagerStockInStable = PoolManagerStockInStable.div(divisionOracle); + + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + // await printFees(stableMasterEUR, managerBTC); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + + it('success - SLP exit', async () => { + const divisionOracle = BigNumber.from('3'); + await ( + await stableMasterEUR.connect(user).withdraw(slpDeposit, user.address, user.address, managerBTC.address) + ).wait(); + + const collatData = await stableMasterEUR.collateralMap(managerBTC.address); + const sanRate = await collatData.sanRate; + const slpData = await collatData.slpData; + + const slpWithdrawInStable = slpDeposit + .mul(BASE_PARAMS.sub(slpData.slippage)) + .mul(sanRate) + .div(BASE_PARAMS) + .div(BASE) + .div(divisionOracle); + PoolManagerStockInStable = PoolManagerStockInStable.sub(slpWithdrawInStable); + const expectedCollatRatio = PoolManagerStockInStable.mul(BASE_PARAMS).div(stableOut); + + const collatRatio = await stableMasterEUR.getCollateralRatio(); + + expect(collatRatio.toString()).to.be.equal(expectedCollatRatio.toString()); + + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + await testKeeperUpdateFee(stableMasterEUR, managerBTC, expectedCollatRatio); + }); + }); +}); + +describe('Total User Fees ', function () { + let coveredRatio = parseAmount.ether(0); + let stockUser = parseAmount.ether(0); + let coveredAmount = parseAmount.ether(0); + + before(async function () { + ({ deployer, guardian, user, ha, slp } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + oracle: oracleBTC, + manager: managerBTC, + feeManager: feeManagerContract, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(18), false)); + collatBASE = BigNumber.from(10).pow(BigNumber.from(18)); + + // update stockuser with the true value + maxAlock = await perpEURBTC.targetHAHedge(); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + await wBTC.connect(user).mint(user.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(stableMasterEUR.address, parseAmount.ether(1000)); + await wBTC.connect(ha).mint(ha.address, parseAmount.ether(1000)); + await wBTC.connect(ha).approve(perpEURBTC.address, parseAmount.ether(1000)); + await wBTC.connect(slp).mint(slp.address, parseAmount.ether(1000)); + await wBTC.connect(slp).approve(stableMasterEUR.address, parseAmount.ether(1000)); + }); + + it('reverts - overflow on amount', async () => { + // fees are computed using the fee structure and what we had covered + // There was before a `computeUserFees` function we could use + const fee = BigNumber.from('80000000'); + + await testMintBurnFee(true, stableMasterEUR, managerBTC, parseAmount.ether(0), fee); + }); + + it('success - 1st mint and cover a tenth', async () => { + const fee = BigNumber.from('80000000'); + + stockUser = stockUser.add(mintAmount).mul(BASE_RATE); + coveredRatio = coveredAmount.mul(parseAmount.gwei(1)).div(stockUser); + + await testMintBurnFee(true, stableMasterEUR, managerBTC, coveredRatio, fee); + + stockUser.sub(mintAmount.mul(BASE_RATE).mul(fee).div(BASE)); + + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + await ( + await perpEURBTC + .connect(ha) + .openPerpetual( + ha.address, + broughtAmount, + commitAmount, + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ) + ).wait(); + + // update stockuser with the true value + const collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + + // update values + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + const curRate = await oracleBTC.readUpper(); + coveredAmount = coveredAmount.add(commitAmount.mul(curRate).div(collatBASE)); + }); + + it('success - after SLP enters with half BASE', async () => { + await (await stableMasterEUR.connect(slp).deposit(slpDeposit, slp.address, managerBTC.address)).wait(); + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + stockUser = stockUser.add(mintAmount.mul(BASE_RATE)); + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE_PARAMS); + coveredRatio = coveredAmount.mul(parseAmount.gwei(1)).div(colFromUsersToCover); + + let collatData = await stableMasterEUR.collateralMap(managerBTC.address); + + const prevBalance = await agEUR.balanceOf(user.address); + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + const newBalance = await agEUR.balanceOf(user.address); + const curOracle = await oracleBTC.readLower(); + const deltaStable = newBalance.sub(prevBalance); + const trueFee = mintAmount.sub(deltaStable.mul(BASE).div(curOracle)).mul(BASE_PARAMS).div(mintAmount); + await testMintBurnFee(true, stableMasterEUR, managerBTC, coveredRatio, trueFee); + + // update stockuser with the true value + collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + }); + + it('success - oracle divided by 3', async () => { + const divisionOracle = BigNumber.from('3'); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE).div(divisionOracle))).wait(); + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + stockUser = stockUser.add(await oracleBTC.readQuoteLower(mintAmount)); + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE_PARAMS); + coveredRatio = coveredAmount.mul(parseAmount.gwei(1)).div(colFromUsersToCover); + + let collatData = await stableMasterEUR.collateralMap(managerBTC.address); + + const prevBalance = await agEUR.balanceOf(user.address); + await (await stableMasterEUR.connect(user).mint(mintAmount, user.address, managerBTC.address, 0)).wait(); + const newBalance = await agEUR.balanceOf(user.address); + const curOracle = await oracleBTC.readLower(); + const deltaStable = newBalance.sub(prevBalance); + const trueFee = mintAmount.sub(deltaStable.mul(BASE).div(curOracle)).mul(BASE_PARAMS).div(mintAmount); + await testMintBurnFee(true, stableMasterEUR, managerBTC, coveredRatio, trueFee); + + // update stockuser with the true value + collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + }); + + it('success - user exit partially', async () => { + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + + stockUser = stockUser.sub(burnAmount); + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE_PARAMS); + coveredRatio = coveredAmount.mul(parseAmount.gwei(1)).div(colFromUsersToCover); + + let collatData = await stableMasterEUR.collateralMap(managerBTC.address); + + const prevBalance = await wBTC.balanceOf(user.address); + await ( + await stableMasterEUR.connect(user).burn(burnAmount, user.address, user.address, managerBTC.address, 0) + ).wait(); + const newBalance = await wBTC.balanceOf(user.address); + const curOracle = await oracleBTC.readUpper(); + const deltaStable = newBalance.sub(prevBalance).mul(curOracle).div(collatBASE); + const trueFee = BASE_PARAMS.sub(deltaStable.mul(BASE_PARAMS).div(burnAmount)); + await testMintBurnFee(false, stableMasterEUR, managerBTC, coveredRatio, trueFee); + + // update stockuser with the true value + collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + }); + it('success - SLP and HA exit User exit partially', async () => { + const curOracle = await oracleBTC.readUpper(); + + await ( + await stableMasterEUR.connect(slp).withdraw(slpDeposit, slp.address, slp.address, managerBTC.address) + ).wait(); + await (await perpEURBTC.connect(ha).closePerpetual(1, ha.address, parseAmount.ether('0'))).wait(); + await (await feeManagerContract.connect(guardian).updateUsersSLP()).wait(); + coveredAmount = coveredAmount.sub(commitAmount.mul(curOracle).div(collatBASE)); + + stockUser = stockUser.sub(burnAmount); + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE_PARAMS); + coveredRatio = BigNumber.from(0).mul(parseAmount.gwei(1)).div(colFromUsersToCover); + + const prevBalance = await wBTC.balanceOf(user.address); + await ( + await stableMasterEUR.connect(user).burn(burnAmount, user.address, user.address, managerBTC.address, 0) + ).wait(); + const newBalance = await wBTC.balanceOf(user.address); + const deltaStable = newBalance.sub(prevBalance).mul(curOracle).div(collatBASE); + const trueFee = BASE_PARAMS.sub(deltaStable.mul(BASE_PARAMS).div(burnAmount)); + await testMintBurnFee(false, stableMasterEUR, managerBTC, coveredRatio, trueFee); + }); +}); + +describe('Total ha fees', function () { + let coveredRatio = parseAmount.ether(0); + let stockUser = parseAmount.ether(0); + let coveredAmount = parseAmount.ether(0); + let nbrPerpetual = 0; + + before(async function () { + ({ deployer, guardian, user, ha, slp } = await ethers.getNamedSigners()); + ({ ANGLE, stableMaster: stableMasterEUR, agToken: agEUR } = await initAngle(deployer, guardian)); + ({ + token: wBTC, + oracle: oracleBTC, + manager: managerBTC, + feeManager: feeManagerContract, + perpetualManager: perpEURBTC, + } = await initCollateral('wBTC', stableMasterEUR, ANGLE, deployer, BigNumber.from(18), false)); + collatBASE = BigNumber.from(10).pow(BigNumber.from(18)); + + // update stockuser with the true value + maxAlock = await perpEURBTC.targetHAHedge(); + + await (await oracleBTC.connect(deployer).update(BASE_RATE.mul(BASE_ORACLE))).wait(); + + await wBTC.connect(user).mint(user.address, parseAmount.ether(1000)); + await wBTC.connect(user).approve(stableMasterEUR.address, parseAmount.ether(1000)); + await wBTC.connect(ha).mint(ha.address, parseAmount.ether(1000)); + await wBTC.connect(ha).approve(perpEURBTC.address, parseAmount.ether(1000)); + await wBTC.connect(slp).mint(slp.address, parseAmount.ether(1000)); + await wBTC.connect(slp).approve(stableMasterEUR.address, parseAmount.ether(1000)); + }); + it('success - 1st mint and cover a tenth', async () => { + await (await stableMasterEUR.connect(user).mint(mintAmount, ha.address, managerBTC.address, 0)).wait(); + // update stockuser with the true value + const collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE_PARAMS); + coveredAmount = coveredAmount.add(commitAmount.mul(BASE_RATE)); + coveredRatio = coveredAmount.mul(parseAmount.gwei(1)).div(colFromUsersToCover); + + await ( + await perpEURBTC + .connect(ha) + .openPerpetual( + ha.address, + broughtAmount, + commitAmount, + parseAmount.ether('10000000000000000'), + parseAmount.ether(0), + ) + ).wait(); + nbrPerpetual += 1; + stockUser = collatData.stocksUsers; + + const perpUser = await perpEURBTC.perpetualData(nbrPerpetual); + const netMargin = perpUser.margin; + const trueFee = broughtAmount.sub(netMargin); + await testHAFee(0, perpEURBTC, coveredRatio, trueFee, commitAmount); + }); + it('success - HA cashout', async () => { + const perpUser = await perpEURBTC.perpetualData(nbrPerpetual); + const netMargin = perpUser.margin; + + const colFromUsersToCover = stockUser.mul(maxAlock).div(BASE); + coveredRatio = coveredAmount + .sub(commitAmount.mul(perpUser.entryRate).div(collatBASE)) + .mul(parseAmount.ether(1)) + .div(colFromUsersToCover); + + const prevBalance = await wBTC.balanceOf(ha.address); + await (await perpEURBTC.connect(ha).closePerpetual(nbrPerpetual, ha.address, BigNumber.from(0))).wait(); + const newBalance = await wBTC.balanceOf(ha.address); + + const collatData = await stableMasterEUR.collateralMap(managerBTC.address); + stockUser = collatData.stocksUsers; + + const trueFee = netMargin.sub(newBalance.sub(prevBalance)); + await testHAFee(1, perpEURBTC, coveredRatio, trueFee, commitAmount); + }); +}); + +async function testKeeperUpdateFee( + contract: StableMasterFront, + collateral: PoolManager, + expectedCollateral: BigNumber, +) { + const collatData = await contract.collateralMap(collateral.address); + const feeData = await collatData.feeData; + const slpData = await collatData.slpData; + + let expectedFee = piecewiseFunction(expectedCollateral, xBonusMalusMint, yBonusMalusMint); + expect(feeData.bonusMalusMint.toString()).to.be.equal(expectedFee.toString()); + + expectedFee = piecewiseFunction(expectedCollateral, xBonusMalusBurn, yBonusMalusBurn); + expect(feeData.bonusMalusBurn.toString()).to.be.equal(expectedFee.toString()); + + expectedFee = piecewiseFunction(expectedCollateral, xSlippage, ySlippage); + expect(slpData.slippage.toString()).to.be.equal(expectedFee.toString()); + + expectedFee = piecewiseFunction(expectedCollateral, xSlippageFee, ySlippageFee); + expect(slpData.slippageFee.toString()).to.be.equal(expectedFee.toString()); +} + +async function testMintBurnFee( + mint: boolean, + contract: StableMasterFront, + collateral: PoolManager, + coveredRatio: BigNumber, + incuredFee: BigNumber, +) { + const collatData = await contract.collateralMap(collateral.address); + const feeData = await collatData.feeData; + + let personalFee: BigNumber; + let globalFee: BigNumber; + if (mint) { + personalFee = piecewiseFunction(coveredRatio, xFeeMint, yFeeMint); + globalFee = feeData.bonusMalusMint; + } else { + personalFee = piecewiseFunction(coveredRatio, xFeeBurn, yFeeBurn); + globalFee = feeData.bonusMalusBurn; + } + const expectedFee = personalFee.mul(globalFee).div(parseAmount.gwei(1)); + // we approximate by an order of 10 (which means precision of 10**17 if working in BASE = 10**18) + // because the incurred fee is computed with the round on the other side + const orderApprox = BigNumber.from(1); + expect(incuredFee.div(orderApprox).toString()).to.be.equal(expectedFee.div(orderApprox).toString()); +} + +async function testHAFee( + action: number, + contract: PerpetualManagerFront, + coveredRatio: BigNumber, + incuredPaidFee: BigNumber, + commit: BigNumber, +) { + let personalFee: BigNumber; + let globalFee: BigNumber; + switch (action) { + // this to add + case 0: { + personalFee = piecewiseFunction(coveredRatio, xHAFeesDeposit, yHAFeesDeposit); + globalFee = await contract.haBonusMalusDeposit(); + break; + } + // this to remove + case 1: { + personalFee = piecewiseFunction(coveredRatio, xHAFeesWithdraw, yHAFeesWithdraw); + globalFee = await contract.haBonusMalusWithdraw(); + break; + } + // this to liquidate + default: { + // to be changed + personalFee = piecewiseFunction(coveredRatio, xHAFeesWithdraw, yHAFeesWithdraw); + globalFee = await contract.haBonusMalusWithdraw(); + break; + } + } + const expectedFee = personalFee.mul(globalFee).div(parseAmount.gwei(1)); + const expectedPaidFee = commit.mul(expectedFee).div(parseAmount.gwei(1)); + expect(incuredPaidFee.toString()).to.be.equal(expectedPaidFee.toString()); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..455cc47 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "resolveJsonModule": true + }, + "include": ["./scripts", "test", "./deploy", "./deploy/rinkeby"], + "files": ["./hardhat.config.ts"] +} diff --git a/utils/bignumber.ts b/utils/bignumber.ts new file mode 100644 index 0000000..ec384f5 --- /dev/null +++ b/utils/bignumber.ts @@ -0,0 +1,81 @@ +import { utils, BigNumber, BigNumberish } from 'ethers'; + +export function mwei(number: BigNumberish): BigNumber { + return utils.parseUnits(number.toString(), 'mwei'); +} + +// gweiToBN +export function gwei(number: BigNumberish): BigNumber { + return utils.parseUnits(number.toString(), 'gwei'); +} +function formatGwei(number: BigNumberish): string { + return utils.formatUnits(number, 'gwei'); +} + +function ether(number: BigNumberish): BigNumber { + return utils.parseUnits(number.toString(), 'ether'); +} +function formatEther(number: BigNumberish): string { + return utils.formatEther(number); +} + +function dai(number: BigNumberish): BigNumber { + return utils.parseUnits(number.toString(), 18); +} +function formatDai(number: BigNumberish): string { + return utils.formatEther(number); +} + +function usdc(number: BigNumberish): BigNumber { + return utils.parseUnits(number.toString(), 6); +} +function formatUsdc(number: BigNumberish): string { + return utils.formatUnits(number, 6); +} + +function general(number: BigNumberish, decimal: number): BigNumber { + return utils.parseUnits(number.toString(), decimal); +} +function formatGeneral(number: BigNumberish, decimal: number): string { + return utils.formatUnits(number, decimal); +} + +export const parseAmount = { + ether, + dai, + usdc, + gwei, + general, +}; + +export const formatAmount = { + ether: formatEther, + dai: formatDai, + usdc: formatUsdc, + gwei: formatGwei, + general: formatGeneral, +}; + +export function multByPow(number: number | BigNumber, pow: number | BigNumber): BigNumber { + return utils.parseUnits(number.toString(), pow); +} + +// +export function multBy10e15(number: number | BigNumber): BigNumber { + return utils.parseUnits(number.toString(), 15); +} + +// gweiToBN +export function multBy10e9(number: number): BigNumber { + return utils.parseUnits(number.toString(), 'gwei'); +} + +// BNtoEth +export function divBy10e18(bigNumber: BigNumberish): number { + return parseFloat(utils.formatUnits(bigNumber, 'ether')); +} + +// BNtoEth +export function divBy10ePow(bigNumber: BigNumberish, pow: number | BigNumber): number { + return parseFloat(utils.formatUnits(bigNumber, pow)); +} diff --git a/utils/network.ts b/utils/network.ts new file mode 100644 index 0000000..472f253 --- /dev/null +++ b/utils/network.ts @@ -0,0 +1,44 @@ +import 'dotenv/config'; + +export function nodeUrl(networkName: string): string { + if (networkName) { + const uri = process.env['ETH_NODE_URI_' + networkName.toUpperCase()]; + if (uri && uri !== '') { + return uri; + } + } + + let uri = process.env.ETH_NODE_URI; + if (uri) { + uri = uri.replace('{{networkName}}', networkName); + } + if (!uri || uri === '') { + if (networkName === 'localhost') { + return 'http://localhost:8545'; + } + return ''; + } + if (uri.indexOf('{{') >= 0) { + throw new Error(`invalid uri or network not supported by node provider : ${uri}`); + } + return uri; +} + +export function getMnemonic(networkName: string): string { + if (networkName) { + const mnemonic = process.env['MNEMONIC_' + networkName.toUpperCase()]; + if (mnemonic && mnemonic !== '') { + return mnemonic; + } + } + + const mnemonic = process.env.MNEMONIC; + if (!mnemonic || mnemonic === '') { + return 'test test test test test test test test test test test junk'; + } + return mnemonic; +} + +export function accounts(networkName: string): { mnemonic: string; count: number; } { + return { mnemonic: getMnemonic(networkName), count: 20 }; +} diff --git a/utils/uniswap.ts b/utils/uniswap.ts new file mode 100644 index 0000000..53688a4 --- /dev/null +++ b/utils/uniswap.ts @@ -0,0 +1,159 @@ +import { Pool } from '@uniswap/v3-sdk'; +import { Token } from '@uniswap/sdk-core'; +import { abi as IUniswapV3PoolABI } from '@uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json'; +import { ethers } from 'hardhat'; +import Web3 from 'web3'; +import { PoolAddress } from '../typechain'; + + + +interface Immutables { + factory: string; + token0: string; + token1: string; + fee: number; + tickSpacing: number; + maxLiquidityPerTick: ethers.BigNumber; +} + +interface State { + liquidity: ethers.BigNumber; + sqrtPriceX96: ethers.BigNumber; + tick: number; + observationIndex: number; + observationCardinality: number; + observationCardinalityNext: number; + feeProtocol: number; + unlocked: boolean; +} + +async function getPoolImmutables(poolAddress: string) { + const poolContract = new ethers.Contract(poolAddress, IUniswapV3PoolABI, ethers.provider); + const [factory, token0, token1, fee, tickSpacing, maxLiquidityPerTick] = await Promise.all([ + poolContract.factory(), + poolContract.token0(), + poolContract.token1(), + poolContract.fee(), + poolContract.tickSpacing(), + poolContract.maxLiquidityPerTick(), + ]); + + const immutables: Immutables = { + factory, + token0, + token1, + fee, + tickSpacing, + maxLiquidityPerTick, + }; + return immutables; +} +async function getPoolState(poolAddress: string) { + const poolContract = new ethers.Contract(poolAddress, IUniswapV3PoolABI, ethers.provider); + const [liquidity, slot] = await Promise.all([poolContract.liquidity(), poolContract.slot0()]); + + const PoolState: State = { + liquidity, + sqrtPriceX96: slot[0], + tick: slot[1], + observationIndex: slot[2], + observationCardinality: slot[3], + observationCardinalityNext: slot[4], + feeProtocol: slot[5], + unlocked: slot[6], + }; + + return PoolState; +} + +export async function getTokenPriceFromUniswap( + poolAddress: string, + _tokenIn: { address: string; decimals: number }, + _tokenOut: { address: string; decimals: number }, +): Promise { + const [immutables, state] = await Promise.all([getPoolImmutables(poolAddress), getPoolState(poolAddress)]); + + const tokenIn = new Token(1, _tokenIn.address, _tokenIn.decimals, 'FEI', 'FEI'); + const tokenOut = new Token(1, _tokenOut.address, _tokenOut.decimals, 'USDC', 'USDC'); + + const pool = new Pool( + tokenIn, + tokenOut, + immutables.fee, + state.sqrtPriceX96.toString(), + state.liquidity.toString(), + state.tick, + ); + // console.log(pool, pool.token0Price.toFixed(), pool.token1Price.toFixed()); + return pool.token0.address === _tokenIn.address ? pool.token0Price.toFixed() : pool.token1Price.toFixed(); +} + + +type PoolKey = { + token0: string, + token1:string, + fee: number, +} + + + // require(key.token0 < key.token1); + // pool = address( + // uint160( + // uint256( + // keccak256( + // abi.encodePacked( + // hex"ff", + // factory, + // keccak256(abi.encode(key.token0, key.token1, key.fee)), + // _POOL_INIT_CODE_HASH + // ) + // ) + // ) + // ) + // ); + +async function main() { + const { deployer } = await ethers.getNamedSigners(); + + + // tmp + const poolAddressContract = '0x029F049C59A6b56610a34ba01d0d28E26ed407A8'; + + // Params + const _POOL_INIT_CODE_HASH = '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'; + const FEIAddress = '0x956F47F50A910163D8BF957Cf5846D573E7f87CA'; + const USDCAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; + const uniFee = 500; + let key: PoolKey; + + if (FEIAddress < USDCAddress) { + key = { token0: FEIAddress, token1: USDCAddress, fee: uniFee }; + } else { + } + const GuardianRoleHash = Web3.utils.soliditySha3('GUARDIAN_ROLE')!; + + // EXAMPLE with FEI-USDC + const POOLADDRESS = '0xdf50fbde8180c8785842c8e316ebe06f542d3443'; // FEI-USDC + getTokenPriceFromUniswap( + POOLADDRESS, + { address: '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', decimals: 18 }, + { address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', decimals: 6 }, + ); + + const contractUniPoolAddress = new ethers.Contract( + poolAddressContract, + [ + 'function getPoolKey(address tokenA, address tokenB, uint24 fee) external pure returns ((address token0,address token1, uint24 fee))', + ], + deployer, + ) as PoolAddress; + + const poolKey = await contractUniPoolAddress.connect(deployer).getPoolKey(USDCAddress, FEIAddress, uniFee); + + console.log('the pool key is ', poolKey); +} + +main().catch(error => { + console.error(error); + process.exit(1); +}); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..63225fd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,13034 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@angleprotocol/sdk@1.0.38": + version "1.0.38" + resolved "https://registry.yarnpkg.com/@angleprotocol/sdk/-/sdk-1.0.38.tgz#ae32ba3c63038a285903daa5ed3857315ffe77af" + integrity sha512-BjR/HMOQu3JI28/nRL10sXJ+JXrdjTPABUeNrSlXcVhMoewEaDkdqWQi43DtD8CINpK/VtORUPAagi3OyMpM0A== + dependencies: + "@typechain/ethers-v5" "^8.0.5" + ethers "^5.5.1" + graphql "^15.7.1" + graphql-request "^3.6.1" + tiny-invariant "^1.1.0" + typechain "^6.0.5" + +"@babel/code-frame@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/runtime@^7.4.4": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@ensdomains/address-encoder@^0.1.7": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@ensdomains/address-encoder/-/address-encoder-0.1.9.tgz#f948c485443d9ef7ed2c0c4790e931c33334d02d" + integrity sha512-E2d2gP4uxJQnDu2Kfg1tHNspefzbLT8Tyjrm5sEuim32UkU2sm5xL4VXtgc2X33fmPEw9+jUMpGs4veMbf+PYg== + dependencies: + bech32 "^1.1.3" + blakejs "^1.1.0" + bn.js "^4.11.8" + bs58 "^4.0.1" + crypto-addr-codec "^0.1.7" + nano-base32 "^1.0.1" + ripemd160 "^2.0.2" + +"@ensdomains/ens@0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.3.tgz#f4a6b55146fe526c9a50e13f373bf90d36ca94dc" + integrity sha512-btC+fGze//ml8SMNCx5DgwM8+kG2t+qDCZrqlL/2+PV4CNxnRIpR3egZ49D9FqS52PFoYLmz6MaQfl7AO3pUMA== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + ethereumjs-testrpc "^6.0.3" + ganache-cli "^6.1.0" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + 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" + +"@ensdomains/ensjs@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@ensdomains/ensjs/-/ensjs-2.0.1.tgz#c27438f9ca074825ddb08430988c7decf2062a91" + integrity sha512-gZLntzE1xqPNkPvaHdJlV5DXHms8JbHBwrXc2xNrL1AylERK01Lj/txCCZyVQqFd3TvUO1laDbfUv8VII0qrjg== + dependencies: + "@babel/runtime" "^7.4.4" + "@ensdomains/address-encoder" "^0.1.7" + "@ensdomains/ens" "0.4.3" + "@ensdomains/resolver" "0.2.4" + content-hash "^2.5.2" + eth-ens-namehash "^2.0.8" + ethers "^5.0.13" + js-sha3 "^0.8.0" + +"@ensdomains/resolver@0.2.4", "@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@eslint/eslintrc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3" + integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.1" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@ethereum-waffle/chai@^3.4.0": + version "3.4.3" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.3.tgz#a2fbaa583f02164c6a5c755df488f45482f6f382" + integrity sha512-yu1DCuyuEvoQFP9PCbHqiycGxwKUrZ24yc/DsjkBlLAQ3OSLhbmlbMiz804YFymWCNsFmobEATp6kBuUDexo7w== + dependencies: + "@ethereum-waffle/provider" "^3.4.1" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" + integrity sha512-a2wxGOoB9F1QFRE+Om7Cz2wn+pxM/o7a0a6cbwhaS2lECJgFzeN9xEkVrKahRkF4gEfXGcuORg4msP0Asxezlw== + dependencies: + "@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.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.1.tgz#0f1b7ac4fc156641c18accd60f8ce256e2c475cf" + integrity sha512-xSjNWnT2Iwii3J3XGqD+F5yLEOzQzLHNLGfI5KIXdtQ4FHgReW/AMGRgPPLi+n+SP08oEQWJ3sEKrvbFlwJuaA== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.1.tgz#dfd53a6e184f5e4c5e1119a8aef67f2d88914497" + integrity sha512-h9yChF7IkpJLODg/o9/jlwKwTcXJLSEIq3gewgwUJuBHnhPkJGekcZvsTbximYc+e42QUZrDUATSuTCIryeCEA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.0", "@ethereum-waffle/provider@^3.4.1": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.1.tgz#d59f5741d5ee96a7d5501f455709b38d81c8be2f" + integrity sha512-5iDte7c9g9N1rTRE/P4npwk1Hus/wA2yH850X6sP30mr1IrwSG9NKn6/2SOQkAVJnh9jqyLVg2X9xCODWL8G4A== + dependencies: + "@ethereum-waffle/ens" "^3.3.1" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0", "@ethereumjs/block@^3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.1.tgz#50574d3e993ae247dcfe2abbdb91d2a4a22accb9" + integrity sha512-o5d/zpGl4SdVfdTfrsq9ZgYMXddc0ucKMiFW5OphBCX+ep4xzYnSjboFcZXT2V/tcSBr84VrKWWp21CGVb3DGw== + dependencies: + "@ethereumjs/common" "^2.6.1" + "@ethereumjs/tx" "^3.5.0" + ethereumjs-util "^7.1.4" + merkle-patricia-tree "^4.2.3" + +"@ethereumjs/blockchain@^5.5.0", "@ethereumjs/blockchain@^5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz#60f1f50592c06cc47e1704800b88b7d32f609742" + integrity sha512-JS2jeKxl3tlaa5oXrZ8mGoVBCz6YqsGG350XVNtHAtNZXKk7pU3rH4xzF2ru42fksMMqzFLzKh9l4EQzmNWDqA== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/ethash" "^1.1.0" + debug "^2.2.0" + ethereumjs-util "^7.1.3" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + +"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.0", "@ethereumjs/common@^2.6.1", "@ethereumjs/common@^2.6.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.2.tgz#eb006c9329c75c80f634f340dc1719a5258244df" + integrity sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.4" + +"@ethereumjs/ethash@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" + integrity sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA== + dependencies: + "@ethereumjs/block" "^3.5.0" + "@types/levelup" "^4.3.0" + buffer-xor "^2.0.1" + ethereumjs-util "^7.1.1" + miller-rabin "^4.0.0" + +"@ethereumjs/tx@^3.2.1", "@ethereumjs/tx@^3.3.2", "@ethereumjs/tx@^3.4.0", "@ethereumjs/tx@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.0.tgz#783b0aeb08518b9991b23f5155763bbaf930a037" + integrity sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw== + dependencies: + "@ethereumjs/common" "^2.6.1" + ethereumjs-util "^7.1.4" + +"@ethereumjs/vm@^5.6.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.7.1.tgz#3bf757fbad0081838ccb4f22003cd73319ab3616" + integrity sha512-NiFm5FMaeDGZ9ojBL+Y9Y/xhW6S4Fgez+zPBM402T5kLsfeAR9mrRVckYhvkGVJ6FMwsY820CLjYP5OVwMjLTg== + dependencies: + "@ethereumjs/block" "^3.6.1" + "@ethereumjs/blockchain" "^5.5.1" + "@ethereumjs/common" "^2.6.2" + "@ethereumjs/tx" "^3.5.0" + async-eventemitter "^0.2.4" + core-js-pure "^3.0.1" + debug "^4.3.3" + ethereumjs-util "^7.1.4" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + merkle-patricia-tree "^4.2.3" + rustbn.js "~0.2.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + 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" + +"@ethersproject/abi@5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" + integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== + 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" + +"@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" + integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" + integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + +"@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.4.1", "@ethersproject/abstract-signer@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" + integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/address@5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" + integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + +"@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" + integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + +"@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" + integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" + integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" + integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" + integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + +"@ethersproject/contracts@5.5.0", "@ethersproject/contracts@^5.4.1": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" + integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== + dependencies: + "@ethersproject/abi" "^5.5.0" + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + +"@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" + integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" + integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" + integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" + integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" + integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== + +"@ethersproject/networks@5.5.2", "@ethersproject/networks@^5.5.0": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.2.tgz#784c8b1283cd2a931114ab428dae1bd00c07630b" + integrity sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" + integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + +"@ethersproject/properties@5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" + integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/providers@5.5.3", "@ethersproject/providers@^5.4.4": + version "5.5.3" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.3.tgz#56c2b070542ac44eb5de2ed3cf6784acd60a3130" + integrity sha512-ZHXxXXXWHuwCQKrgdpIkbzMNJMvs+9YWemanwp1fA7XZEv7QlilseysPvQe0D7Q7DlkJX/w/bGA1MdgK2TbGvA== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.5.1", "@ethersproject/random@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.1.tgz#7cdf38ea93dc0b1ed1d8e480ccdaf3535c555415" + integrity sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" + integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" + integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" + integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.5.0", "@ethersproject/solidity@^5.4.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" + integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/strings@5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" + integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0", "@ethersproject/transactions@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" + integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + +"@ethersproject/units@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" + integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/wallet@5.5.0", "@ethersproject/wallet@^5.4.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" + integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/json-wallets" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" + integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== + dependencies: + "@ethersproject/base64" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" + integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" + integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.0.tgz#11553ba06de0d1352332c1bde28c8edd00e0dcf6" + integrity sha512-LczOjjxY4A7XYloxzyxJIHONELmUxVZncpOLoClpEcTiebiVdM46KRPYXGuULro9oNNR2xdVx3yoKiQjdfWmoA== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers": + version "0.3.0-beta.13" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" + integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== + +"@nomiclabs/hardhat-solhint@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.0.tgz#28f2c6b50709a91538ba69c1c8fe60985bf920f3" + integrity sha512-fn+izC923/oCnfbGyp7YwOXZYtwcrDIrTLlFVeEgeSAHe2ZnipRRtNCxEClZuzCptHmTzIIayBmAaijsTmEAoA== + dependencies: + solhint "^2.0.0" + +"@nomiclabs/hardhat-web3@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-web3/-/hardhat-web3-2.0.0.tgz#2d9850cb285a2cebe1bd718ef26a9523542e52a9" + integrity sha512-zt4xN+D+fKl3wW2YlTX3k9APR3XZgPkxJYf36AcliJn3oujnKEVRZaHu0PhgLjO+gR+F/kiYayo9fgd2L8970Q== + dependencies: + "@types/bignumber.js" "^5.0.0" + +"@openzeppelin/contract-loader@^0.6.2": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contract-loader/-/contract-loader-0.6.3.tgz#61a7b44de327e40b7d53f39e0fb59bbf847335c3" + integrity sha512-cOFIjBjwbGgZhDZsitNgJl0Ye1rd5yu/Yx5LMgeq3u0ZYzldm4uObzHDFq4gjDdoypvyORjjJa3BlFA7eAnVIg== + dependencies: + find-up "^4.1.0" + fs-extra "^8.1.0" + +"@openzeppelin/contracts-upgradeable@4.5.1": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.1.tgz#dc354082460eb34f5833afdecfab46538b208c4f" + integrity sha512-xcKycsSyFauIGMhSeeTJW/Jzz9jZUJdiFNP9Wo/9VhMhw8t5X0M92RY6x176VfcIWsxURMHFWOJVTlFA78HI/w== + +"@openzeppelin/contracts@4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" + integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== + +"@openzeppelin/hardhat-upgrades@1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.14.0.tgz#a84c4088061959164468ae10a2ae53faaa3163fd" + integrity sha512-dWLC+cgawHcZ5AbEblA3nTrBpcG9J7Z7J5UmM7qdsc/Yc97USJjXfcD6uYOQ+PhyFVBY0Ni83WGVll48d4QRWQ== + dependencies: + "@openzeppelin/upgrades-core" "^1.12.0" + chalk "^4.1.0" + +"@openzeppelin/test-helpers@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@openzeppelin/test-helpers/-/test-helpers-0.5.15.tgz#7727d4bb1535e1fa2372d65d1dcee335ce8d36af" + integrity sha512-10fS0kyOjc/UObo9iEWPNbC6MCeiQ7z97LDOJBj68g+AAs5pIGEI2h3V6G9TYTIq8VxOdwMQbfjKrx7Y3YZJtA== + dependencies: + "@openzeppelin/contract-loader" "^0.6.2" + "@truffle/contract" "^4.0.35" + ansi-colors "^3.2.3" + chai "^4.2.0" + chai-bn "^0.2.1" + ethjs-abi "^0.2.1" + lodash.flatten "^4.4.0" + semver "^5.6.0" + web3 "^1.2.5" + web3-utils "^1.2.5" + +"@openzeppelin/upgrades-core@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.12.0.tgz#847aeeba38780040672f8288795c824a4c9d97e6" + integrity sha512-gu/ijQW+RJqGlniNkpNmiwBus3R1cuJNT0/MEJASWRFNr4Qvn0d7LZONaAkhnvlBpxdiiPenMcFIrRlwvZL4iw== + dependencies: + bn.js "^5.1.2" + cbor "^8.0.0" + chalk "^4.1.0" + compare-versions "^4.0.0" + debug "^4.1.1" + ethereumjs-util "^7.0.3" + proper-lockfile "^4.1.1" + solidity-ast "^0.4.15" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + 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" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@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@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@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" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@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@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" + integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@truffle/abi-utils@^0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-0.2.8.tgz#d7210451dc612340bff0d260ed8499ddb099678f" + integrity sha512-n/9ojMthWuP1hg9JveuxctxWoRoKTh+/17RTSwlTlXTyP/kfoNxr1JcLecybXUDOIsLJ4uskqxVUZQDvj1B0PQ== + dependencies: + change-case "3.0.2" + faker "^5.3.1" + fast-check "^2.12.1" + +"@truffle/blockchain-utils@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@truffle/blockchain-utils/-/blockchain-utils-0.1.0.tgz#96742866e5d0274dd715402610162dbf51e31e6f" + integrity sha512-9mzYXPQkjOc23rHQM1i630i3ackITWP1cxf3PvBObaAnGqwPCQuqtmZtNDPdvN+YpOLpBGpZIdYolI91xLdJNQ== + +"@truffle/codec@^0.11.26": + version "0.11.26" + resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.11.26.tgz#81f476f7e89888b03a1f1531c5688ab7eb9c8b25" + integrity sha512-wNVw66vSL5RSzgNMkiQVIExz7ZF1ZDNdOSPTnFlTiZCvkpJn8QJ9OpDiow9w8HmXIftt+YjueBsKu4ByyBuAPA== + dependencies: + "@truffle/abi-utils" "^0.2.8" + "@truffle/compile-common" "^0.7.27" + big.js "^5.2.2" + bn.js "^5.1.3" + cbor "^5.1.0" + debug "^4.3.1" + lodash.clonedeep "^4.5.0" + lodash.escaperegexp "^4.1.2" + lodash.partition "^4.6.0" + lodash.sum "^4.0.2" + semver "^7.3.4" + utf8 "^3.0.0" + web3-utils "1.5.3" + +"@truffle/compile-common@^0.7.27": + version "0.7.27" + resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.7.27.tgz#8b07b31152f8098be2e3a05f610b8b1c42a977b6" + integrity sha512-gs266BQTRnVoskoWj7wNrNGACMOhU6Yt+8YhaSp6k5e4/a2NBEluxXWxKIi32yWz4q7Ip306do1wcQR2fFOf8w== + dependencies: + "@truffle/error" "^0.1.0" + colors "1.4.0" + +"@truffle/contract-schema@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@truffle/contract-schema/-/contract-schema-3.4.4.tgz#e98f30c5db91f8ca6f239f2a27029b05e3dadf5b" + integrity sha512-xWgrm6WRM2jmT04w7dP7aVbS2qyP9XPmH/mybQtFXMjJ/8BZlp0yltC8QOs8sGl6q8Ws7acp19YtRkLdK6SsmQ== + dependencies: + ajv "^6.10.0" + debug "^4.3.1" + +"@truffle/contract@^4.0.35": + version "4.4.8" + resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.4.8.tgz#e3e7043d1346db02ed538cb983913b982bf54410" + integrity sha512-zZVgIJ4zbdKX1dWubX5m9w7StMpcdEXuQorSpPQ23SUD1RwzSgnRi9Iw2rmSLNbHcO+w6L6+JFeVzFrfmI/VKA== + dependencies: + "@ensdomains/ensjs" "^2.0.1" + "@truffle/blockchain-utils" "^0.1.0" + "@truffle/contract-schema" "^3.4.4" + "@truffle/debug-utils" "^6.0.8" + "@truffle/error" "^0.1.0" + "@truffle/interface-adapter" "^0.5.11" + bignumber.js "^7.2.1" + debug "^4.3.1" + ethers "^4.0.32" + web3 "1.5.3" + web3-core-helpers "1.5.3" + web3-core-promievent "1.5.3" + web3-eth-abi "1.5.3" + web3-utils "1.5.3" + +"@truffle/debug-utils@^6.0.8": + version "6.0.8" + resolved "https://registry.yarnpkg.com/@truffle/debug-utils/-/debug-utils-6.0.8.tgz#4d3994bb08b8b9fde73aebc25d191334ce179117" + integrity sha512-bkrHQZj6OVw5FCs0li69e0f6gdW+6FuOR8dgedfy8qpsVVtGQB+8cN7hnoFUwMs60vo7vW90grZu1c4855zVQw== + dependencies: + "@truffle/codec" "^0.11.26" + "@trufflesuite/chromafi" "^2.2.2" + bn.js "^5.1.3" + chalk "^2.4.2" + debug "^4.3.1" + highlightjs-solidity "^2.0.3" + +"@truffle/error@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.1.0.tgz#5e9fed79e6cda624c926d314b280a576f8b22a36" + integrity sha512-RbUfp5VreNhsa2Q4YbBjz18rOQI909pG32bghl1hulO7IpvcqTS+C3Ge5cNbiWQ1WGzy1wIeKLW0tmQtHFB7qg== + +"@truffle/interface-adapter@^0.5.11": + version "0.5.11" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.11.tgz#209864ba2d1ee7d45ee9a6add8c65f421e23376b" + integrity sha512-HXLm+r1KdT8nHzJht1iK6EnHBKIjSYHdDfebBMCqmRCsMoUXvUJ0KsIxvDG758MafB12pjx5gsNn4XzzfksSBQ== + dependencies: + bn.js "^5.1.3" + ethers "^4.0.32" + web3 "1.5.3" + +"@truffle/provider@^0.2.24": + version "0.2.46" + resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.2.46.tgz#3922d1cb2606c7d1dbd41543720e5ac2448e830e" + integrity sha512-nYZNzONLrksWQJn6iiiUvXJ+EE4IDOouyvJfD1xO75ELTHcRMXh216EacJ/4Irp7uDuANHsbdrLgFT7nN6uUGw== + dependencies: + "@truffle/error" "^0.1.0" + "@truffle/interface-adapter" "^0.5.11" + web3 "1.5.3" + +"@trufflesuite/chromafi@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@trufflesuite/chromafi/-/chromafi-2.2.2.tgz#d3fc507aa8504faffc50fb892cedcfe98ff57f77" + integrity sha512-mItQwVBsb8qP/vaYHQ1kDt2vJLhjoEXJptT6y6fJGvFophMFhOI/NsTVUa0nJL1nyMeFiS6hSYuNVdpQZzB1gA== + dependencies: + ansi-mark "^1.0.0" + ansi-regex "^3.0.0" + array-uniq "^1.0.3" + camelcase "^4.1.0" + chalk "^2.3.2" + cheerio "^1.0.0-rc.2" + detect-indent "^5.0.0" + he "^1.1.1" + highlight.js "^10.4.1" + lodash.merge "^4.6.2" + min-indent "^1.0.0" + strip-ansi "^4.0.0" + strip-indent "^2.0.0" + super-split "^1.1.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@typechain/ethers-v5@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-9.0.0.tgz#6aa93bea7425c0463bd8a61eea3643540ef851bd" + integrity sha512-bAanuPl1L2itaUdMvor/QvwnIH+TM/CmG00q17Ilv3ZZMeJ2j8HcarhgJUZ9pBY1teBb85P8cC03dz3mSSx+tQ== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/ethers-v5@^8.0.5": + version "8.0.5" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-8.0.5.tgz#d469420e9a73deb7fa076cde9edb45d713dd1b8c" + integrity sha512-ntpj4cS3v4WlDu+hSKSyj9A3o1tKtWC30RX1gobeYymZColeJiUemC1Kgfa0MWGmInm5CKxoHVhEvYVgPOZn1A== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/hardhat@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-4.0.0.tgz#976d4dcc0d9237602d722801d30adc573c529981" + integrity sha512-SeEKtiHu4Io3LHhE8VV3orJbsj7dwJZX8pzSTv7WQR38P18vOLm2M52GrykVinMpkLK0uVc88ICT58emvfn74w== + dependencies: + fs-extra "^9.1.0" + +"@types/abstract-leveldown@*": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#f055979a99f7654e84d6b8e6267419e9c4cfff87" + integrity sha512-q5veSX6zjUy/DlDhR4Y4cU0k2Ar+DT2LUraP00T19WLmTO6Se1djepCCaqU6nQrwcJ5Hyo/CWqxTzrrFg8eqbQ== + +"@types/bignumber.js@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969" + integrity sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA== + dependencies: + bignumber.js "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + +"@types/chai-as-promised@^7.1.4": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.2.21": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/concat-stream@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" + integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.0": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" + integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/estree@^0.0.50": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + +"@types/form-data@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + integrity sha1-yayFsqX9GENbjIXZ7LUObWyJP/g= + dependencies: + "@types/node" "*" + +"@types/fs-extra@^9.0.13": + version "9.0.13" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" + integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA== + dependencies: + "@types/node" "*" + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/level-errors@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/level-errors/-/level-errors-3.0.0.tgz#15c1f4915a5ef763b51651b15e90f6dc081b96a8" + integrity sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ== + +"@types/levelup@^4.3.0": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-4.3.3.tgz#4dc2b77db079b1cf855562ad52321aa4241b8ef4" + integrity sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA== + dependencies: + "@types/abstract-leveldown" "*" + "@types/level-errors" "*" + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^9.0.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" + integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== + +"@types/node-fetch@^2.5.5": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*", "@types/node@^17.0.17": + version "17.0.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c" + integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw== + +"@types/node@^10.0.3": + version "10.17.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" + integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== + +"@types/node@^12.12.6": + version "12.20.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.45.tgz#f4980d177999299d99cd4b290f7f39366509a44f" + integrity sha512-1Jg2Qv5tuxBqgQV04+wO5u+wmSHbHgpORCJdeCLM+E+YdPElpdHhgywU+M1V1InL8rfOtpqtOjswk+uXTKwx7w== + +"@types/node@^8.0.0": + version "8.10.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" + integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== + +"@types/qs@^6.2.31", "@types/qs@^6.9.7": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@17.0.8": + version "17.0.8" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.8.tgz#d23a3476fd3da8a0ea44b5494ca7fa677b9dad4c" + integrity sha512-wDeUwiUmem9FzsyysEwRukaEdDNcwbROvQ9QGRKaLI6t+IltNzbn4/i4asmB10auvZGQCzSQ6t0GSczEThlUXw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.11.0.tgz#3b866371d8d75c70f9b81535e7f7d3aa26527c7a" + integrity sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw== + dependencies: + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/type-utils" "5.11.0" + "@typescript-eslint/utils" "5.11.0" + debug "^4.3.2" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/parser@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.11.0.tgz#b4fcaf65513f9b34bdcbffdda055724a5efb7e04" + integrity sha512-x0DCjetHZYBRovJdr3U0zG9OOdNXUaFLJ82ehr1AlkArljJuwEsgnud+Q7umlGDFLFrs8tU8ybQDFocp/eX8mQ== + dependencies: + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/typescript-estree" "5.11.0" + debug "^4.3.2" + +"@typescript-eslint/scope-manager@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz#f5aef83ff253f457ecbee5f46f762298f0101e4b" + integrity sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA== + dependencies: + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/visitor-keys" "5.11.0" + +"@typescript-eslint/type-utils@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz#58be0ba73d1f6ef8983d79f7f0bc2209b253fefe" + integrity sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA== + dependencies: + "@typescript-eslint/utils" "5.11.0" + debug "^4.3.2" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.11.0.tgz#ba345818a2540fdf2755c804dc2158517ab61188" + integrity sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ== + +"@typescript-eslint/typescript-estree@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz#53f9e09b88368191e52020af77c312a4777ffa43" + integrity sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg== + dependencies: + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/visitor-keys" "5.11.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.11.0.tgz#d91548ef180d74c95d417950336d9260fdbe1dc5" + integrity sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/typescript-estree" "5.11.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz#888542381f1a2ac745b06d110c83c0b261487ebb" + integrity sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA== + dependencies: + "@typescript-eslint/types" "5.11.0" + eslint-visitor-keys "^3.0.0" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@uniswap/v3-core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" + integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== + +"@vue/component-compiler-utils@^3.1.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz#f9f5fb53464b0c37b2c8d2f3fbfe44df60f61dc9" + integrity sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ== + dependencies: + consolidate "^0.15.1" + hash-sum "^1.0.2" + lru-cache "^4.1.2" + merge-source-map "^1.1.0" + postcss "^7.0.36" + postcss-selector-parser "^6.0.2" + source-map "~0.6.1" + vue-template-es2015-compiler "^1.9.0" + optionalDependencies: + prettier "^1.18.2 || ^2.0.0" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" + integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" + integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +accepts@~1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-dynamic-import@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" + integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= + dependencies: + acorn "^4.0.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn-jsx@^5.0.0, acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^4.0.3: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + +acorn@^5.0.0: + version "5.7.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" + integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== + +acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +acorn@^8.4.1, acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +address@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.6.1, ajv@^6.9.1: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-colors@4.1.1, ansi-colors@^4.1.0, ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-mark@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ansi-mark/-/ansi-mark-1.0.4.tgz#1cd4ba8d57f15f109d6aaf6ec9ca9786c8a4ee6c" + integrity sha1-HNS6jVfxXxCdaq9uycqXhsik7mw= + dependencies: + ansi-regex "^3.0.0" + array-uniq "^1.0.3" + chalk "^2.3.2" + strip-ansi "^4.0.0" + super-split "^1.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-parents@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha1-UI/Q8F0MSHddnszaLhdEIyYejdM= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@1.x, async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + 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" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + 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" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + 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" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + 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" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + 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" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + 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" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + 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" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + 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" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + 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" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + 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" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + 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" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.0.2, base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + 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" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4, bech32@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +big-integer@1.6.36: + version "1.6.36" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36" + integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +bignumber.js@*, bignumber.js@^9.0.0, bignumber.js@^9.0.1: + version "9.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + +bignumber.js@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bip66@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= + dependencies: + safe-buffer "^5.0.1" + +blakejs@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" + integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + +bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +body-parser@1.19.1, body-parser@^1.16.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" + integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== + dependencies: + bytes "3.1.1" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.6" + raw-body "2.4.2" + type-is "~1.6.18" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + 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" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + 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" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + 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" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.14.5: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + +bs58@^4.0.0, bs58@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.6.tgz#ebd6c67c7922a0e902f053e5d8be5ec850e48433" + integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== + dependencies: + node-gyp-build "^4.3.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" + integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + 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" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + 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" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001286: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== + +caseless@^0.12.0, caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +cbor@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" + integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== + dependencies: + bignumber.js "^9.0.1" + nofilter "^1.0.4" + +cbor@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + +chai-bn@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/chai-bn/-/chai-bn-0.3.1.tgz#677cd3c0b58bae83ffe51604a811d0b3c6f41544" + integrity sha512-vuzEy0Cb+k8zqi2SHOmvZdRSbKcSOJfS1Nv8+6YDJIyCzfxkTCHLNRyjRIoRJ3WJtYb/c7OHjrvLoGeyO4A/gA== + +chai-bn@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/chai-bn/-/chai-bn-0.2.2.tgz#4dcf30dbc79db2378a00781693bc749c972bf34f" + integrity sha512-MzjelH0p8vWn65QKmEq/DLBG1Hle4WeyqT79ANhXZhn/UxRWO0OogkAxi5oGGtfzwU9bZR8mvbvYdoqNVWQwFg== + +chai@^4.2.0, chai@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + 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" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +change-case@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.0.2.tgz#fd48746cce02f03f0a672577d1d3a8dc2eceb037" + integrity sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA== + dependencies: + camel-case "^3.0.0" + constant-case "^2.0.0" + dot-case "^2.1.0" + header-case "^1.0.0" + is-lower-case "^1.1.0" + is-upper-case "^1.1.0" + lower-case "^1.1.1" + lower-case-first "^1.0.0" + no-case "^2.3.2" + param-case "^2.1.0" + pascal-case "^2.0.0" + path-case "^2.1.0" + sentence-case "^2.1.0" + snake-case "^2.1.0" + swap-case "^1.1.0" + title-case "^2.1.0" + upper-case "^1.1.1" + upper-case-first "^1.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +"charenc@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= + dependencies: + functional-red-black-tree "^1.0.1" + +cheerio-select@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" + integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== + dependencies: + css-select "^4.1.3" + css-what "^5.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + domutils "^2.7.0" + +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.10" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" + integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== + dependencies: + cheerio-select "^1.5.0" + dom-serializer "^1.3.2" + domhandler "^4.2.0" + htmlparser2 "^6.1.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + tslib "^2.2.0" + +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + 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" + optionalDependencies: + fsevents "~2.1.1" + +chokidar@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + 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" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-css@^5.2.2: + version "5.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" + integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== + dependencies: + source-map "~0.6.0" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cli-table3@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" + integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== + dependencies: + string-width "^4.2.0" + optionalDependencies: + colors "1.4.0" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colors@1.4.0, colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.1.tgz#c908e28686108917758a49f45efb4f02f76bc03f" + integrity sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA== + dependencies: + array-back "^4.0.1" + chalk "^2.4.2" + table-layout "^1.0.1" + typical "^5.2.0" + +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +compare-versions@^4.0.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-4.1.3.tgz#8f7b8966aef7dc4282b45dfa6be98434fc18a1a4" + integrity sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +consolidate@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" + integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw== + dependencies: + bluebird "^3.1.1" + +constant-case@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" + integrity sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY= + dependencies: + snake-case "^2.1.0" + upper-case "^1.1.1" + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.5.1: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookiejar@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-pure@^3.0.1: + version "3.21.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.0.tgz#819adc8dfb808205ce25b51d50591becd615db7e" + integrity sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +crc-32@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.1.tgz#436d2bcaad27bcb6bd073a2587139d3024a16460" + integrity sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.3.1" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + 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" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.5.tgz#afaf5729f3b6c78d89c9296115c9f142541a5705" + integrity sha512-xqYAhQb4NhCJSRym03dwxpP1bYXpK3y7UN83Bo2WFi3x1Zmzn0SL/6xGoPr+gpt4WmNrgCCX3HPysvOwFOW36w== + dependencies: + node-fetch "2.6.1" + whatwg-fetch "2.0.4" + +cross-fetch@^3.0.6: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +"crypt@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + +crypto-addr-codec@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.7.tgz#e16cea892730178fe25a38f6d15b680cab3124ae" + integrity sha512-X4hzfBzNhy4mAc3UpiXEC/L0jo5E8wAa9unsnA8nNXYzXjCcGk83hfC5avJWCSGT8V91xMnAS9AKMHmjw5+XCg== + dependencies: + base-x "^3.0.8" + big-integer "1.6.36" + blakejs "^1.1.0" + bs58 "^4.0.1" + ripemd160-min "0.0.6" + safe-buffer "^5.2.0" + sha3 "^2.1.1" + +crypto-browserify@3.12.0, crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + 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" + +css-loader@^6.5.1: + version "6.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" + integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.5" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + +css-select@^4.1.3: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== + dependencies: + boolbase "^1.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^5.0.1, css-what@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" + integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +dayjs@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" + integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= + +death@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +debug@^3.1.0, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + 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" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +deferred-leveldown@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" + integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== + dependencies: + abstract-leveldown "~6.2.1" + inherits "^2.0.3" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + +detect-port@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" + integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@^1.0.1, dom-serializer@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +dot-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee" + integrity sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4= + dependencies: + no-case "^2.2.0" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" + integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +drbg.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= + dependencies: + browserify-aes "^1.0.6" + create-hash "^1.1.2" + create-hmac "^1.1.4" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.17: + version "1.4.68" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.68.tgz#d79447b6bd1bec9183f166bb33d4bef0d5e4e568" + integrity sha512-cId+QwWrV8R1UawO6b9BR1hnkJ4EJPCPAr4h315vliHUtVUJDk39Sg1PMNnaWKfj5x+93ssjeJ9LKL6r8LaMiA== + +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + 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" + +emoji-regex@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.0.tgz#96559e19f82231b436403e059571241d627c42b8" + integrity sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding-down@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" + integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== + dependencies: + abstract-leveldown "^6.2.1" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" + integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + object-assign "^4.0.1" + tapable "^0.2.7" + +enhanced-resolve@^5.8.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" + integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +enquirer@^2.3.0, enquirer@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +errno@^0.1.3, errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-prettier@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" + integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + +eslint-config-standard@16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" + integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import@2.25.4: + version "2.25.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" + integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.2" + has "^1.0.3" + is-core-module "^2.8.0" + is-glob "^4.0.3" + minimatch "^3.0.4" + object.values "^1.1.5" + resolve "^1.20.0" + tsconfig-paths "^3.12.0" + +eslint-plugin-mocha-no-only@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha-no-only/-/eslint-plugin-mocha-no-only-1.1.1.tgz#2da56949776e8c5455cfeb67f2747d2d8cf522fc" + integrity sha512-b+vgjJQ3SjRQCygBhomtjzvRQRpIP8Yd9cqwNSbcoVJREuNajao7M1Kl1aObAUc4wx98qsZyQyUSUxiAbMS9yA== + dependencies: + requireindex "~1.1.0" + +eslint-plugin-node@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" + integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-promise@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz#017652c07c9816413a41e11c30adc42c3d55ff18" + integrity sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw== + +eslint-plugin-standard@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz#c43f6925d669f177db46f095ea30be95476b1ee4" + integrity sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg== + +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@8.9.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb" + integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q== + dependencies: + "@eslint/eslintrc" "^1.1.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.6.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== + dependencies: + acorn "^8.7.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^3.3.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.1, esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + 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" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-gas-reporter@^0.2.20: + version "0.2.24" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.24.tgz#768721fec7de02b566e4ebfd123466d275d7035c" + integrity sha512-RbXLC2bnuPHzIMU/rnLXXlb6oiHEEKu7rq2UrAX/0mfo0Lzrr/kb9QTjWjfz8eNvc+uu6J8AuBwI++b+MLNI2w== + dependencies: + "@ethersproject/abi" "^5.0.0-beta.146" + "@solidity-parser/parser" "^0.14.0" + cli-table3 "^0.5.0" + colors "1.4.0" + 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" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + 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" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + 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" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + 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" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + 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" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + 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" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= + +ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + 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" + +ethereum-waffle@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" + integrity sha512-ADBqZCkoSA5Isk486ntKJVjFEawIiC+3HxNqpJqONvh3YXBTNiRfXvJtGuAFLXPG91QaqkGqILEHANAo7j/olQ== + dependencies: + "@ethereum-waffle/chai" "^3.4.0" + "@ethereum-waffle/compiler" "^3.4.0" + "@ethereum-waffle/mock-contract" "^3.3.0" + "@ethereum-waffle/provider" "^3.4.0" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + 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" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + 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" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + 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" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-testrpc@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" + integrity sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA== + dependencies: + webpack "^3.0.0" + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960" + integrity sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ== + 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" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + 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" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + 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" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.3, ethereumjs-util@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" + integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + 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" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + 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" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + 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" + +ethers@5.5.4, ethers@^5.0.1, ethers@^5.0.13, ethers@^5.0.2, ethers@^5.5.1, ethers@^5.5.2: + version "5.5.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352" + integrity sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw== + dependencies: + "@ethersproject/abi" "5.5.0" + "@ethersproject/abstract-provider" "5.5.1" + "@ethersproject/abstract-signer" "5.5.0" + "@ethersproject/address" "5.5.0" + "@ethersproject/base64" "5.5.0" + "@ethersproject/basex" "5.5.0" + "@ethersproject/bignumber" "5.5.0" + "@ethersproject/bytes" "5.5.0" + "@ethersproject/constants" "5.5.0" + "@ethersproject/contracts" "5.5.0" + "@ethersproject/hash" "5.5.0" + "@ethersproject/hdnode" "5.5.0" + "@ethersproject/json-wallets" "5.5.0" + "@ethersproject/keccak256" "5.5.0" + "@ethersproject/logger" "5.5.0" + "@ethersproject/networks" "5.5.2" + "@ethersproject/pbkdf2" "5.5.0" + "@ethersproject/properties" "5.5.0" + "@ethersproject/providers" "5.5.3" + "@ethersproject/random" "5.5.1" + "@ethersproject/rlp" "5.5.0" + "@ethersproject/sha2" "5.5.0" + "@ethersproject/signing-key" "5.5.0" + "@ethersproject/solidity" "5.5.0" + "@ethersproject/strings" "5.5.0" + "@ethersproject/transactions" "5.5.0" + "@ethersproject/units" "5.5.0" + "@ethersproject/wallet" "5.5.0" + "@ethersproject/web" "5.5.1" + "@ethersproject/wordlists" "5.5.0" + +ethers@^4.0.32, ethers@^4.0.40: + version "4.0.49" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" + integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== + dependencies: + aes-js "3.0.0" + bn.js "^4.11.9" + elliptic "6.5.4" + 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" + +ethjs-abi@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.2.1.tgz#e0a7a93a7e81163a94477bad56ede524ab6de533" + integrity sha1-4KepOn6BFjqUR3utVu3lJKtt5TM= + dependencies: + bn.js "4.11.6" + js-sha3 "0.5.5" + number-to-bn "1.7.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0, events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.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" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + 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" + +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + 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" + +express@^4.14.0: + version "4.17.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" + integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.4.1" + 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.7" + qs "6.9.6" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + 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" + +extract-files@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" + integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= + dependencies: + checkpoint-store "^1.1.0" + +faker@^5.3.1: + version "5.5.3" + resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" + integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== + +fast-check@^2.12.1: + version "2.21.0" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.21.0.tgz#0d2e20bc65343ee67ec0f58373358140c08a1217" + integrity sha512-hkTRytqMceXfnSwPnryIqKkxKJjfcvtVqJrWRb8tgmfyUsGajIgQqDFxCJ+As+l9VLUCcmx6XIYoXeQe2Ih0UA== + dependencies: + pure-rand "^5.0.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.0.3, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= + dependencies: + node-fetch "~1.7.1" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + 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" + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha1-x7vxJN7ELJ0ZHPuUfQqXeN2YbAw= + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1, follow-redirects@^1.14.0: + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" + integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +ganache-cli@^6.1.0, ganache-cli@^6.12.2: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.12.2.tgz#c0920f7db0d4ac062ffe2375cb004089806f627a" + integrity sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw== + dependencies: + ethereumjs-util "6.2.1" + source-map-support "0.5.12" + yargs "13.2.4" + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + 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 "3.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" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-port@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +ghost-testrpc@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" + integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== + dependencies: + chalk "^2.4.2" + node-emoji "^1.10.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + 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" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + 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" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + 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" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.7.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.12.1" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" + integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== + dependencies: + type-fest "^0.20.2" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + 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" + +globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +got@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + 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" + +got@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + 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" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +graphql-request@^3.6.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.7.0.tgz#c7406e537084f8b9788541e3e6704340ca13055b" + integrity sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ== + dependencies: + cross-fetch "^3.0.6" + extract-files "^9.0.0" + form-data "^3.0.0" + +graphql@^15.7.1: + version "15.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" + integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +handlebars@^4.0.1: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hardhat-abi-exporter@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.8.0.tgz#e7ed6216c16acf84158909d856577f0a8832ec55" + integrity sha512-HQwd9Agr2O5znUg9Dzicw8grsXacoMSQsS5ZhBBNyaxKeVbvxL1Ubm9ss8sSVGr74511a8qiR2Ljm/lsLS9Mew== + dependencies: + "@ethersproject/abi" "^5.5.0" + delete-empty "^3.0.0" + +hardhat-contract-sizer@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.4.0.tgz#3cc125937aa3d773283851085de99c9bd31a7828" + integrity sha512-ww+Fw5Fq+q6gkVxB8KFvicqZFH5pH9HGZwV4ZSTxd0QrxA162qzLdbScJseUP30VvIBPYN9wpdj0cWlz6M9j6g== + dependencies: + chalk "^4.0.0" + cli-table3 "^0.6.0" + +hardhat-deploy@0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.10.5.tgz#d3f8ea85220f201110ce9205a601f27b369cc918" + integrity sha512-qBfcOfROd/WPbimxX0ZkcDyohD5DK2HrROIgRABiDvsyl8DjN7z8SRvoAGjBdUA34ov/pN3zXW1MBVGil3t7pg== + dependencies: + "@ethersproject/abi" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.1" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.1" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/contracts" "^5.4.1" + "@ethersproject/providers" "^5.4.4" + "@ethersproject/solidity" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/wallet" "^5.4.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + +hardhat-docgen@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/hardhat-docgen/-/hardhat-docgen-1.3.0.tgz#604c685cb92c4231c8d84b2d81c017fb887ff1d8" + integrity sha512-paaiOHjJFLCLz2/qM1TQ7ZEG+Vy+LBvJL+SW4A64ZhBnVnyoZ/zv9DvEuawaWhqP5P7AOM6r22reVz4ecWgW7A== + dependencies: + css-loader "^6.5.1" + html-webpack-plugin "^5.5.0" + vue "^2.6.14" + vue-loader "^15.9.8" + vue-router "^3.5.3" + vue-template-compiler "^2.6.14" + webpack "^5.65.0" + +hardhat-gas-reporter@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.4.tgz#59e3137e38e0dfeac2e4f90d5c74160b50ad4829" + integrity sha512-G376zKh81G3K9WtDA+SoTLWsoygikH++tD1E7llx+X7J+GbIqfwhDKKgvJjcnEesMrtR9UqQHK02lJuXY1RTxw== + dependencies: + eth-gas-reporter "^0.2.20" + sha1 "^1.1.1" + +hardhat-spdx-license-identifier@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/hardhat-spdx-license-identifier/-/hardhat-spdx-license-identifier-2.0.3.tgz#6dd89a7e036ede4f7e86fb349eb23daaaad6890f" + integrity sha512-G4u4I1md0tWaitX6Os7Nq9sYZ/CFdR+ibm7clCksGJ4yrtdHEZxgLjWpJ0WiALF9SoFKt03PwCe9lczDQ/5ADA== + +hardhat@2.8.4: + version "2.8.4" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.8.4.tgz#b12cc8b8ea578fc6cefbcd9683d558adc302152d" + integrity sha512-lEwvQSbhABpKgBTJnRgdZ6nZZRmgKUF2G8aGNaBVIQnJeRZjELnZHLIWXAF1HW0Q1NFCyo9trxOrOuzmiS+r/w== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + "@ethereumjs/vm" "^5.6.0" + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.0" + "@types/bn.js" "^5.1.0" + "@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" + ethereum-cryptography "^0.1.2" + ethereumjs-abi "^0.6.8" + ethereumjs-util "^7.1.3" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "^7.1.3" + https-proxy-agent "^5.0.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + lodash "^4.17.11" + merkle-patricia-tree "^4.2.2" + mnemonist "^0.38.0" + mocha "^7.2.0" + 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 "^8.3.2" + ws "^7.4.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash-sum@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= + +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0, he@^1.1.0, he@^1.1.1, he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +header-case@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" + integrity sha1-lTWXMZfBRLCWE81l0xfvGZY70C0= + dependencies: + no-case "^2.2.0" + upper-case "^1.1.3" + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= + +highlight.js@^10.4.1: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +highlightjs-solidity@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/highlightjs-solidity/-/highlightjs-solidity-2.0.3.tgz#c89b6eca7d462f849acfb3a94c18f7db2b6d0c69" + integrity sha512-tjFm5dtIE61VQBzjlZmkCtY5fLs3CaEABbVuUNyXeW+UuOCsxMg3MsPFy0kCelHP74hPpkoqDejLrbnV1axAIw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-webpack-plugin@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" + integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +http-basic@^8.1.1: + version "8.1.3" + resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" + integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== + dependencies: + caseless "^0.12.0" + concat-stream "^1.6.2" + http-response-object "^3.0.1" + parse-cache-control "^1.0.1" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-response-object@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" + integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== + dependencies: + "@types/node" "^10.0.3" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +immutable@^4.0.0-rc.12: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk= + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.8.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-lower-case@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" + integrity sha1-fhR75HaNxGbbO/shzGCzHmrWk5M= + dependencies: + lower-case "^1.1.0" + +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-retry-allowed@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.3, is-typed-array@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" + integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-upper-case@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" + integrity sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8= + dependencies: + upper-case "^1.1.0" + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-sha3@0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" + integrity sha1-uvDA6MVK1ZA0R9+Wreekobynmko= + +js-sha3@0.5.7, js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-loader@^0.5.4: + version "0.5.7" + resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== + +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + 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" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonschema@^1.2.4: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" + integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b" + integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q== + dependencies: + bindings "^1.5.0" + inherits "^2.0.4" + nan "^2.14.0" + safe-buffer "^5.2.0" + +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-concat-iterator@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" + integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-iterator-stream@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" + integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== + dependencies: + inherits "^2.0.4" + readable-stream "^3.4.0" + xtend "^4.0.2" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-mem@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d" + integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg== + dependencies: + level-packager "^5.0.3" + memdown "^5.0.0" + +level-packager@^5.0.3: + version "5.1.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" + integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== + dependencies: + encoding-down "^6.3.0" + levelup "^4.3.2" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + 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" + +level-supports@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" + integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== + dependencies: + xtend "^4.0.2" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +level-ws@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339" + integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA== + dependencies: + inherits "^2.0.3" + readable-stream "^3.1.0" + xtend "^4.0.1" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + 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" + +levelup@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" + integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== + dependencies: + 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" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + 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" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +loader-runner@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + +loader-utils@^1.0.2, loader-utils@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= + +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.partition@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.partition/-/lodash.partition-4.6.0.tgz#a38e46b73469e0420b0da1212e66d414be364ba4" + integrity sha1-o45GtzRp4EILDaEhLmbUFL42S6Q= + +lodash.sum@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lodash.sum/-/lodash.sum-4.0.2.tgz#ad90e397965d803d4f1ff7aa5b2d0197f3b4637b" + integrity sha1-rZDjl5ZdgD1PH/eqWy0Bl/O0Y3s= + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + +lower-case-first@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" + integrity sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E= + dependencies: + lower-case "^1.1.2" + +lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + dependencies: + pseudomap "^1.0.1" + +lru-cache@^4.0.1, lru-cache@^4.1.2: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-table@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== + +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= + 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" + +memdown@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" + integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== + dependencies: + 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" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + 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" + +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== + dependencies: + source-map "^0.6.1" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + 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" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + 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" + +merkle-patricia-tree@^4.2.2, merkle-patricia-tree@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.3.tgz#b4e5d485d231f02b255ed79a7852f9d12ee0c09f" + integrity sha512-S4xevdXl5KvdBGgUxhQcxoep0onqXiIhzfwZp4M78kIuJH3Pu9o9IUgqhzSFOR2ykLO6t265026Xb6PY0q2UFQ== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + semaphore-async-await "^1.5.1" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + 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" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +"minimatch@2 || 3", minimatch@^3.0.4: + version "3.1.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.1.tgz#879ad447200773912898b46cd516a7abbb5e50b0" + integrity sha512-reLxBcKUPNBnc/sVtAbxgRVFSegoGeLaSjmphNhcwcolhYLRgtJscn5mRl6YRZNQv40Y7P6JM2YhSIsbL9OB5A== + dependencies: + brace-expansion "^1.1.7" + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.2.tgz#e84849b61f406a680ced85af76425f6f3108d1a0" + integrity sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.2" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.23" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.5" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mocha@^7.1.1, mocha@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== + 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" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +nan@^2.12.1, nan@^2.14.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nano-base32@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nano-base32/-/nano-base32-1.0.1.tgz#ba548c879efcfb90da1c4d9e097db4a46c9255ef" + integrity sha1-ulSMh578+5DaHE2eCX20pGySVe8= + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanoid@3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== + +nanoid@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + 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" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^2.2.0, no-case@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" + integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + +node-libs-browser@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-releases@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + +nofilter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" + integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== + +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +nth-check@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" + integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== + dependencies: + boolbase "^1.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.11.0, object-inspect@^1.9.0, object-inspect@~1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +obliterator@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.2.tgz#25f50dc92e1181371b9d8209d11890f1a3c2fc21" + integrity sha512-g0TrA7SbUggROhDPK8cEu/qpItwH2LSKcNl4tlfBNT54XY+nOsqrs0Q68h1V9b3HOSpIWv15jb1lax2hAggdIg== + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + dependencies: + http-https "^1.0.0" + +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= + dependencies: + http-https "^1.0.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.8.1, optionator@^0.8.2: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + 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" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +param-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= + dependencies: + no-case "^2.2.0" + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + 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" + +parse-cache-control@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + integrity sha1-juqz5U+laSD+Fro493+iGqzC104= + +parse-headers@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" + integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse5-htmlparser2-tree-adapter@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" + integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4= + dependencies: + camel-case "^3.0.0" + upper-case-first "^1.1.0" + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + 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" + +patch-package@^6.2.2: + version "6.4.7" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" + integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + 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" + tmp "^0.0.33" + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" + integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU= + dependencies: + no-case "^2.2.0" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-starts-with@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" + integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + 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" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^7.0.36: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^8.4.5: + version "8.4.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== + dependencies: + nanoid "^3.2.0" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier-plugin-solidity@1.0.0-beta.19: + version "1.0.0-beta.19" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" + integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== + dependencies: + "@solidity-parser/parser" "^0.14.0" + emoji-regex "^10.0.0" + escape-string-regexp "^4.0.0" + semver "^7.3.5" + solidity-comments-extractor "^0.0.7" + string-width "^4.2.3" + +prettier@2.5.1, "prettier@^1.18.2 || ^2.0.0", prettier@^2.1.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + +prettier@^1.14.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + +printj@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb" + integrity sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +promise@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" + integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== + dependencies: + asap "~2.0.6" + +proper-lockfile@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.1, pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + 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" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + 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" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.6.14" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" + integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +pure-rand@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-5.0.0.tgz#87f5bdabeadbd8904e316913a5c0b8caac517b37" + integrity sha512-lD2/y78q+7HqBx2SaT6OT4UcwtvXNRfEpzYEzl0EQ+9gZq2Qi3fa0HDnYPeqQwhlHJFBUhT7AO3mLU3+8bynHA== + +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== + +qs@^6.4.0, qs@^6.7.0, qs@^6.9.4: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.2, raw-body@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== + dependencies: + bytes "3.1.1" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + 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" + +readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" + integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpp@^3.0.0, regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +req-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + integrity sha1-1AgrTURZgDZkD7c93qAe1T20nrw= + dependencies: + req-from "^2.0.0" + +req-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + integrity sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA= + dependencies: + resolve-from "^3.0.0" + +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.79.0, request@^2.85.0, request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + 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" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= + +require-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requireindex@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162" + integrity sha1-5UBLgVV+91225JxacgBIk/4D4WI= + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.20.0, resolve@^1.8.1, resolve@~1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + dependencies: + align-text "^0.1.1" + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160-min@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/ripemd160-min/-/ripemd160-min-0.0.6.tgz#a904b77658114474d02503e819dcc55853b67e62" + integrity sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A== + +ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sc-istanbul@^0.4.5: + version "0.4.6" + resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== + 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" + +schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^3.0.1: + version "3.8.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" + integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== + 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" + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore-async-await@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" + integrity sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo= + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.1.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== + 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.8.1" + mime "1.6.0" + ms "2.1.3" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +sentence-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4" + integrity sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ= + dependencies: + no-case "^2.2.0" + upper-case-first "^1.1.2" + +serialize-javascript@6.0.0, serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" + integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.2" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + +setimmediate@^1.0.4, setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg= + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + +sha3@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" + integrity sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg== + dependencies: + buffer "6.0.3" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shelljs@^0.8.3: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +snake-case@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" + integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8= + dependencies: + no-case "^2.2.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + 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" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + 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" + +solc@0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.7.tgz#54434959cc3d69a569ad8853c0d9ee1338da0aab" + integrity sha512-p8Zi+YcGN22P3Stb6KJhNypD9xSnNF3D6eIw6LyxZpMIVpcwrG8fTaXeEbKITmlp14DC1iZ4BC4aV7r7gJ/EJw== + 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" + +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + 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" + +solhint-plugin-prettier@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz#e3b22800ba435cd640a9eca805a7f8bc3e3e6a6b" + integrity sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA== + dependencies: + prettier-linter-helpers "^1.0.0" + +solhint@3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.7.tgz#b5da4fedf7a0fee954cb613b6c55a5a2b0063aa7" + integrity sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ== + dependencies: + "@solidity-parser/parser" "^0.14.1" + ajv "^6.6.1" + antlr4 "4.7.1" + ast-parents "0.0.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + +solhint@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" + integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== + dependencies: + ajv "^6.6.1" + antlr4 "4.7.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + +solidity-ast@^0.4.15: + version "0.4.30" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.30.tgz#402d8277311d6680c786f756ba27e1c19f809293" + integrity sha512-3xsQIbZEPx6w7+sQokuOvk1RkMb5GIpuK0GblQDIH6IAkU4+uyJQVJIRNP+8KwhzkViwRKq0hS4zLqQNLKpxOA== + +solidity-comments-extractor@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" + integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== + +solidity-coverage@0.7.19: + version "0.7.19" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.19.tgz#0d2247c8efc6a6b3e79b94df866125fb8f17aada" + integrity sha512-TjVhKG0+KjlxFk8ECRI6/QVmjfsUr4Cupmlmg7OShbLDLLeCDcl1WSL290+0gZXcB0Zw9ZMsRcIVGYHYk2GQWA== + dependencies: + "@solidity-parser/parser" "^0.14.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.12.2" + 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" + semver "^7.3.4" + shelljs "^0.8.3" + web3-utils "^1.3.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + 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" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.13, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= + dependencies: + amdefine ">=0.0.4" + +source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + 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" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@~1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" + integrity sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + +strip-json-comments@2.0.1, strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +super-split@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/super-split/-/super-split-1.1.0.tgz#43b3ba719155f4d43891a32729d59b213d9155fc" + integrity sha512-I4bA5mgcb6Fw5UJ+EkpzqXfiuvVGS/7MuND+oBxNFmxu3ugLNrdIatzBLfhFRMVMLxgSsRy+TjIktgkF9RFSNQ== + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^4.2.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= + dependencies: + has-flag "^2.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +swap-case@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" + integrity sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM= + dependencies: + lower-case "^1.1.1" + upper-case "^1.1.1" + +swarm-js@^0.1.40: + version "0.1.40" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" + integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== + 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" + +sync-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" + integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== + dependencies: + http-response-object "^3.0.1" + sync-rpc "^1.2.1" + then-request "^6.0.0" + +sync-rpc@^1.2.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" + integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== + dependencies: + get-port "^3.1.0" + +table-layout@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +tapable@^0.2.7: + version "0.2.9" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" + integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== + +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +tape@^4.6.3: + version "4.15.0" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.15.0.tgz#1b8a9563b4bc7e51302216c137732fb2ce6d1a99" + integrity sha512-SfRmG2I8QGGgJE/MCiLH8c11L5XxyUXxwK9xLRD0uiK5fehRkkSZGmR6Y1pxOt8vJ19m3sY+POTQpiaVv45/LQ== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.0" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.0" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.5" + object-inspect "~1.12.0" + resolve "~1.22.0" + resumer "~0.0.0" + string.prototype.trim "~1.2.5" + through "~2.3.8" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +terser-webpack-plugin@^5.1.3: + version "5.3.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" + integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + +terser@^5.10.0, terser@^5.7.2: + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== + dependencies: + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +then-request@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" + integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== + 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" + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.6, through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +timers-browserify@^2.0.4: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + +tiny-invariant@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" + integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + +title-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" + integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o= + dependencies: + no-case "^2.2.0" + upper-case "^1.0.3" + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +"true-case-path@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" + integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== + +ts-command-line-args@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.2.1.tgz#fd6913e542099012c0ffb2496126a8f38305c7d6" + integrity sha512-mnK68QA86FYzQYTSA/rxIjT/8EpKsvQw9QkawPic8I8t0gjAOw3Oa509NIRoaY1FmH7hdrncMp7t7o+vYoceNQ== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + 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" + +ts-node@10.5.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.5.0.tgz#618bef5854c1fbbedf5e31465cbb224a1d524ef9" + integrity sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + +tsconfig-paths@^3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" + integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.3, tslib@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +tweetnacl@^1.0.0, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.6.0.tgz#3ca6099af5981d36ca86b78442973694278a219f" + integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== + +typechain@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-7.0.0.tgz#258ca136de1d451368bde01c318976a83062f110" + integrity sha512-ILfvBBFJ7j9aIk0crX03+N2GmzoDN1gtk32G1+XrasjuvXS0XAw2XxwQeQMMgKwlnxViJjIkG87sTMYXPkXA9g== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + 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" + +typechain@^6.0.5: + version "6.1.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-6.1.0.tgz#462a35f555accf870689d1ba5698749108d0ce81" + integrity sha512-GGfkK0p3fUgz8kYxjSS4nKcWXE0Lo+teHTetghousIK5njbNoYNDlwn91QIyD181L3fVqlTvBE0a/q3AZmjNfw== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +uglify-js@^2.8.29: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-js@^3.1.4: + version "3.15.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d" + integrity sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ== + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + +uglifyjs-webpack-plugin@^0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" + integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= + dependencies: + source-map "^0.5.6" + uglify-js "^2.8.29" + webpack-sources "^1.0.1" + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +upper-case-first@^1.1.0, upper-case-first@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" + integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU= + dependencies: + upper-case "^1.1.1" + +upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.8" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58" + integrity sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + 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" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +vue-hot-reload-api@^2.3.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" + integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== + +vue-loader@^15.9.8: + version "15.9.8" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.8.tgz#4b0f602afaf66a996be1e534fb9609dc4ab10e61" + integrity sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog== + dependencies: + "@vue/component-compiler-utils" "^3.1.0" + hash-sum "^1.0.2" + loader-utils "^1.1.0" + vue-hot-reload-api "^2.3.0" + vue-style-loader "^4.1.0" + +vue-router@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.3.tgz#041048053e336829d05dafacf6a8fb669a2e7999" + integrity sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg== + +vue-style-loader@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35" + integrity sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg== + dependencies: + hash-sum "^1.0.2" + loader-utils "^1.0.2" + +vue-template-compiler@^2.6.14: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763" + integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g== + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + +vue-template-es2015-compiler@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" + integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== + +vue@^2.6.14: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" + integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ== + +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.4.0: + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.1" + +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-bzz@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.5.3.tgz#e36456905ce051138f9c3ce3623cbc73da088c2b" + integrity sha512-SlIkAqG0eS6cBS9Q2eBOTI1XFzqh83RqGJWnyrNZMDxUwsTVHL+zNnaPShVPvrWQA1Ub5b0bx1Kc5+qJVxsTJg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + +web3-bzz@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.7.0.tgz#0b754d787a1700f0580fa741fc707d19d1447ff4" + integrity sha512-XPhTWUnZa8gnARfiqaag3jJ9+6+a66Li8OikgBUJoMUqPuQTCJPncTbGYqOJIfRFGavEAdlMnfYXx9lvgv2ZPw== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-helpers@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.5.3.tgz#099030235c477aadf39a94199ef40092151d563c" + integrity sha512-Ip1IjB3S8vN7Kf1PPjK41U5gskmMk6IJQlxIVuS8/1U7n/o0jC8krqtpRwiMfAgYyw3TXwBFtxSRTvJtnLyXZw== + dependencies: + web3-eth-iban "1.5.3" + web3-utils "1.5.3" + +web3-core-helpers@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.7.0.tgz#0eaef7bc55ff7ec5ba726181d0e8529be5d60903" + integrity sha512-kFiqsZFHJliKF8VKZNjt2JvKu3gu7h3N1/ke3EPhdp9Li/rLmiyzFVr6ApryZ1FSjbSx6vyOkibG3m6xQ5EHJA== + dependencies: + web3-eth-iban "1.7.0" + web3-utils "1.7.0" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + 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" + +web3-core-method@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.5.3.tgz#6cff97ed19fe4ea2e9183d6f703823a079f5132c" + integrity sha512-8wJrwQ2qD9ibWieF9oHXwrJsUGrv3XAtEkNeyvyNMpktNTIjxJ2jaFGQUuLiyUrMubD18XXgLk4JS6PJU4Loeg== + dependencies: + "@ethereumjs/common" "^2.4.0" + "@ethersproject/transactions" "^5.0.0-beta.135" + web3-core-helpers "1.5.3" + web3-core-promievent "1.5.3" + web3-core-subscriptions "1.5.3" + web3-utils "1.5.3" + +web3-core-method@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.7.0.tgz#5e98030ac9e0d96c6ff1ba93fde1292a332b1b81" + integrity sha512-43Om+kZX8wU5u1pJ28TltF9e9pSTRph6b8wrOb6wgXAfPHqMulq6UTBJWjXXIRVN46Eiqv0nflw35hp9bbgnbA== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + web3-core-helpers "1.7.0" + web3-core-promievent "1.7.0" + web3-core-subscriptions "1.7.0" + web3-utils "1.7.0" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-promievent@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.5.3.tgz#3f11833c3dc6495577c274350b61144e0a4dba01" + integrity sha512-CFfgqvk3Vk6PIAxtLLuX+pOMozxkKCY+/GdGr7weMh033mDXEPvwyVjoSRO1PqIKj668/hMGQsVoIgbyxkJ9Mg== + dependencies: + eventemitter3 "4.0.4" + +web3-core-promievent@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.7.0.tgz#e2c6c38f29b912cc549a2a3f806636a3393983eb" + integrity sha512-xPH66XeC0K0k29GoRd0vyPQ07yxERPRd4yVPrbMzGAz/e9E4M3XN//XK6+PdfGvGw3fx8VojS+tNIMiw+PujbQ== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + 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" + +web3-core-requestmanager@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.5.3.tgz#b339525815fd40e3a2a81813c864ddc413f7b6f7" + integrity sha512-9k/Bze2rs8ONix5IZR+hYdMNQv+ark2Ek2kVcrFgWO+LdLgZui/rn8FikPunjE+ub7x7pJaKCgVRbYFXjo3ZWg== + dependencies: + util "^0.12.0" + web3-core-helpers "1.5.3" + web3-providers-http "1.5.3" + web3-providers-ipc "1.5.3" + web3-providers-ws "1.5.3" + +web3-core-requestmanager@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.7.0.tgz#5b62b413471d6d2a789ee33d587d280178979c7e" + integrity sha512-rA3dBTBPrt+eIfTAQ2/oYNTN/2wbZaYNR3pFZGqG8+2oCK03+7oQyz4sWISKy/nYQhURh4GK01rs9sN4o/Tq9w== + dependencies: + util "^0.12.0" + web3-core-helpers "1.7.0" + web3-providers-http "1.7.0" + web3-providers-ipc "1.7.0" + web3-providers-ws "1.7.0" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core-subscriptions@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.5.3.tgz#d7d69c4caad65074212028656e9dc56ca5c2159d" + integrity sha512-L2m9vG1iRN6thvmv/HQwO2YLhOQlmZU8dpLG6GSo9FBN14Uch868Swk0dYVr3rFSYjZ/GETevSXU+O+vhCummA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.5.3" + +web3-core-subscriptions@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.7.0.tgz#30475d8ed5f51a170e5df02085f721925622a795" + integrity sha512-6giF8pyJrPmWrRpc2WLoVCvQdMMADp20ZpAusEW72axauZCNlW1XfTjs0i4QHQBfdd2lFp65qad9IuATPhuzrQ== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.7.0" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + 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" + +web3-core@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.5.3.tgz#59f8728b27c8305b349051326aa262b9b7e907bf" + integrity sha512-ACTbu8COCu+0eUNmd9pG7Q9EVsNkAg2w3Y7SqhDr+zjTgbSHZV01jXKlapm9z+G3AN/BziV3zGwudClJ4u4xXQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-requestmanager "1.5.3" + web3-utils "1.5.3" + +web3-core@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.7.0.tgz#67b7839130abd19476e7f614ea6ec4c64d08eb00" + integrity sha512-U/CRL53h3T5KHl8L3njzCBT7fCaHkbE6BGJe3McazvFldRbfTDEHXkUJCyM30ZD0RoLi3aDfTVeFIusmEyCctA== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-requestmanager "1.7.0" + web3-utils "1.7.0" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-abi@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.5.3.tgz#5aea9394d797f99ca0d9bd40c3417eb07241c96c" + integrity sha512-i/qhuFsoNrnV130CSRYX/z4SlCfSQ4mHntti5yTmmQpt70xZKYZ57BsU0R29ueSQ9/P+aQrL2t2rqkQkAloUxg== + dependencies: + "@ethersproject/abi" "5.0.7" + web3-utils "1.5.3" + +web3-eth-abi@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.7.0.tgz#4fac9c7d9e5a62b57f8884b37371f515c766f3f4" + integrity sha512-heqR0bWxgCJwjWIhq2sGyNj9bwun5+Xox/LdZKe+WMyTSy0cXDXEAgv3XKNkXC4JqdDt/ZlbTEx4TWak4TRMSg== + dependencies: + "@ethersproject/abi" "5.0.7" + web3-utils "1.7.0" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + 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" + +web3-eth-accounts@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.5.3.tgz#076c816ff4d68c9dffebdc7fd2bfaddcfc163d77" + integrity sha512-pdGhXgeBaEJENMvRT6W9cmji3Zz/46ugFSvmnLLw79qi5EH7XJhKISNVb41eWCrs4am5GhI67GLx5d2s2a72iw== + dependencies: + "@ethereumjs/common" "^2.3.0" + "@ethereumjs/tx" "^3.2.1" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + uuid "3.3.2" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-utils "1.5.3" + +web3-eth-accounts@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.7.0.tgz#d0a6f2cfbd61dd6014224056070b7f8d1d63c0ab" + integrity sha512-Zwm7TlQXdXGRuS6+ib1YsR5fQwpfnFyL6UAZg1zERdrUrs3IkCZSL3yCP/8ZYbAjdTEwWljoott2iSqXNH09ug== + dependencies: + "@ethereumjs/common" "^2.5.0" + "@ethereumjs/tx" "^3.3.2" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + uuid "3.3.2" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-utils "1.7.0" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + 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" + +web3-eth-contract@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.5.3.tgz#12b03a4a16ce583a945f874bea2ff2fb4c5b81ad" + integrity sha512-Gdlt1L6cdHe83k7SdV6xhqCytVtOZkjD0kY/15x441AuuJ4JLubCHuqu69k2Dr3tWifHYVys/vG8QE/W16syGg== + dependencies: + "@types/bn.js" "^4.11.5" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-promievent "1.5.3" + web3-core-subscriptions "1.5.3" + web3-eth-abi "1.5.3" + web3-utils "1.5.3" + +web3-eth-contract@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.7.0.tgz#3795767a65d7b87bd22baea3e18aafdd928d5313" + integrity sha512-2LY1Xwxu5rx468nqHuhvupQAIpytxIUj3mGL9uexszkhrQf05THVe3i4OnUCzkeN6B2cDztNOqLT3j9SSnVQDg== + dependencies: + "@types/bn.js" "^4.11.5" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-promievent "1.7.0" + web3-core-subscriptions "1.7.0" + web3-eth-abi "1.7.0" + web3-utils "1.7.0" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + 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" + +web3-eth-ens@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.5.3.tgz#ef6eee1ddf32b1ff9536fc7c599a74f2656bafe1" + integrity sha512-QmGFFtTGElg0E+3xfCIFhiUF+1imFi9eg/cdsRMUZU4F1+MZCC/ee+IAelYLfNTGsEslCqfAusliKOT9DdGGnw== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-promievent "1.5.3" + web3-eth-abi "1.5.3" + web3-eth-contract "1.5.3" + web3-utils "1.5.3" + +web3-eth-ens@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.7.0.tgz#49c5300935b026578aaaf9664e5e5529d4c76a68" + integrity sha512-I1bikYJJWQ/FJZIAvwsGOvzAgcRIkosWG4s1L6veRoXaU8OEJFeh4s00KcfHDxg7GWZZGbUSbdbzKpwRbWnvkg== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-promievent "1.7.0" + web3-eth-abi "1.7.0" + web3-eth-contract "1.7.0" + web3-utils "1.7.0" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-iban@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.5.3.tgz#91b1475893a877b10eac1de5cce6eb379fb81b5d" + integrity sha512-vMzmGqolYZvRHwP9P4Nf6G8uYM5aTLlQu2a34vz78p0KlDC+eV1th3+90Qeaupa28EG7OO0IT1F0BejiIauOPw== + dependencies: + bn.js "^4.11.9" + web3-utils "1.5.3" + +web3-eth-iban@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.7.0.tgz#b56cd58587457d3339730e0cb42772a37141b434" + integrity sha512-1PFE/Og+sPZaug+M9TqVUtjOtq0HecE+SjDcsOOysXSzslNC2CItBGkcRwbvUcS+LbIkA7MFsuqYxOL0IV/gyA== + dependencies: + bn.js "^4.11.9" + web3-utils "1.7.0" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + 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" + +web3-eth-personal@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.5.3.tgz#4ebe09e9a77dd49d23d93b36b36cfbf4a6dae713" + integrity sha512-JzibJafR7ak/Icas8uvos3BmUNrZw1vShuNR5Cxjo+vteOC8XMqz1Vr7RH65B4bmlfb3bm9xLxetUHO894+Sew== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-net "1.5.3" + web3-utils "1.5.3" + +web3-eth-personal@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.7.0.tgz#260c9b6af6e0bea772c6a9a5d58c8d62c035ed99" + integrity sha512-Dr9RZTNOR80PhrPKGdktDUXpOgExEcCcosBj080lKCJFU1paSPj9Zfnth3u6BtIOXyKsVFTrpqekqUDyAwXnNw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-net "1.7.0" + web3-utils "1.7.0" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + 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" + +web3-eth@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.5.3.tgz#d7d1ac7198f816ab8a2088c01e0bf1eda45862fe" + integrity sha512-saFurA1L23Bd7MEf7cBli6/jRdMhD4X/NaMiO2mdMMCXlPujoudlIJf+VWpRWJpsbDFdu7XJ2WHkmBYT5R3p1Q== + dependencies: + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-subscriptions "1.5.3" + web3-eth-abi "1.5.3" + web3-eth-accounts "1.5.3" + web3-eth-contract "1.5.3" + web3-eth-ens "1.5.3" + web3-eth-iban "1.5.3" + web3-eth-personal "1.5.3" + web3-net "1.5.3" + web3-utils "1.5.3" + +web3-eth@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.7.0.tgz#4adbed9b28ab7f81cb11e3586a12d01ab6e812aa" + integrity sha512-3uYwjMjn/MZjKIzXCt4YL9ja/k9X5shfa4lKparZhZE6uesmu+xmSmrEFXA/e9qcveF50jkV7frjkT8H+cLYtw== + dependencies: + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-subscriptions "1.7.0" + web3-eth-abi "1.7.0" + web3-eth-accounts "1.7.0" + web3-eth-contract "1.7.0" + web3-eth-ens "1.7.0" + web3-eth-iban "1.7.0" + web3-eth-personal "1.7.0" + web3-net "1.7.0" + web3-utils "1.7.0" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-net@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.5.3.tgz#545fee49b8e213b0c55cbe74ffd0295766057463" + integrity sha512-0W/xHIPvgVXPSdLu0iZYnpcrgNnhzHMC888uMlGP5+qMCt8VuflUZHy7tYXae9Mzsg1kxaJAS5lHVNyeNw4CoQ== + dependencies: + web3-core "1.5.3" + web3-core-method "1.5.3" + web3-utils "1.5.3" + +web3-net@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.7.0.tgz#694a0c7988f7efc336bab0ee413eb4522efee3b2" + integrity sha512-8pmfU1Se7DmG40Pu8nOCKlhuI12VsVzCtdFDnLAai0zGVAOUuuOCK71B2aKm6u9amWBJjtOlyrCwvsG+QEd6dw== + dependencies: + web3-core "1.7.0" + web3-core-method "1.7.0" + web3-utils "1.7.0" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + 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" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-http@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.5.3.tgz#74f170fc3d79eb7941d9fbc34e2a067d61ced0b2" + integrity sha512-5DpUyWGHtDAr2RYmBu34Fu+4gJuBAuNx2POeiJIooUtJ+Mu6pIx4XkONWH6V+Ez87tZAVAsFOkJRTYuzMr3rPw== + dependencies: + web3-core-helpers "1.5.3" + xhr2-cookies "1.1.0" + +web3-providers-http@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.7.0.tgz#0661261eace122a0ed5853f8be5379d575a9130c" + integrity sha512-Y9reeEiApfvQKLUUtrU4Z0c+H6b7BMWcsxjgoXndI1C5NB297mIUfltXxfXsh5C/jk5qn4Q3sJp3SwQTyVjH7Q== + dependencies: + web3-core-helpers "1.7.0" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ipc@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.5.3.tgz#4bd7f5e445c2f3c2595fce0929c72bb879320a3f" + integrity sha512-JmeAptugVpmXI39LGxUSAymx0NOFdgpuI1hGQfIhbEAcd4sv7fhfd5D+ZU4oLHbRI8IFr4qfGU0uhR8BXhDzlg== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.5.3" + +web3-providers-ipc@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.7.0.tgz#152dc1231eb4f17426498d4d5d973c865eab03d9" + integrity sha512-U5YLXgu6fvAK4nnMYqo9eoml3WywgTym0dgCdVX/n1UegLIQ4nctTubBAuWQEJzmAzwh+a6ValGcE7ZApTRI7Q== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.7.0" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-providers-ws@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.5.3.tgz#eec6cfb32bb928a4106de506f13a49070a21eabf" + integrity sha512-6DhTw4Q7nm5CFYEUHOJM0gAb3xFx+9gWpVveg3YxJ/ybR1BUvEWo3bLgIJJtX56cYX0WyY6DS35a7f0LOI1kVg== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.5.3" + websocket "^1.0.32" + +web3-providers-ws@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.7.0.tgz#99c2de9f6b5ac56e926794ef9074c7442d937372" + integrity sha512-0a8+lVV3JBf+eYnGOsdzOpftK1kis5X7s35QAdoaG5SDapnEylXFlR4xDSSSU88ZwMwvse8hvng2xW6A7oeWxw== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.7.0" + websocket "^1.0.32" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-shh@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.5.3.tgz#3c04aa4cda9ba0b746d7225262401160f8e38b13" + integrity sha512-COfEXfsqoV/BkcsNLRxQqnWc1Teb8/9GxdGag5GtPC5gQC/vsN+7hYVJUwNxY9LtJPKYTij2DHHnx6UkITng+Q== + dependencies: + web3-core "1.5.3" + web3-core-method "1.5.3" + web3-core-subscriptions "1.5.3" + web3-net "1.5.3" + +web3-shh@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.7.0.tgz#ed9d085b670bb5a938f2847393478e33df3ec95c" + integrity sha512-RZhxcevALIPK178VZCpwMBvQeW+IoWtRJ4EMdegpbnETeZaC3aRUcs6vKnrf0jXJjm4J/E2Dt438Y1Ord/1IMw== + dependencies: + web3-core "1.7.0" + web3-core-method "1.7.0" + web3-core-subscriptions "1.7.0" + web3-net "1.7.0" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + 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" + +web3-utils@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.5.3.tgz#e914c9320cd663b2a09a5cb920ede574043eb437" + integrity sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q== + 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" + utf8 "3.0.0" + +web3-utils@1.7.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.2.5, web3-utils@^1.3.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.7.0.tgz#c59f0fd43b2449357296eb54541810b99b1c771c" + integrity sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w== + dependencies: + bn.js "^4.11.9" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + 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" + +web3@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.5.3.tgz#11882679453c645bf33620fbc255a243343075aa" + integrity sha512-eyBg/1K44flfv0hPjXfKvNwcUfIVDI4NX48qHQe6wd7C8nPSdbWqo9vLy6ksZIt9NLa90HjI8HsGYgnMSUxn6w== + dependencies: + web3-bzz "1.5.3" + web3-core "1.5.3" + web3-eth "1.5.3" + web3-eth-personal "1.5.3" + web3-net "1.5.3" + web3-shh "1.5.3" + web3-utils "1.5.3" + +web3@^1.2.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.7.0.tgz#5867cd10a2bebb5c33fc218368e3f6f826f6897e" + integrity sha512-n39O7QQNkpsjhiHMJ/6JY6TaLbdX+2FT5iGs8tb3HbIWOhPm4+a7UDbr5Lkm+gLa9aRKWesZs5D5hWyEvg4aJA== + dependencies: + web3-bzz "1.7.0" + web3-core "1.7.0" + web3-eth "1.7.0" + web3-eth-personal "1.7.0" + web3-net "1.7.0" + web3-shh "1.7.0" + web3-utils "1.7.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +webpack-sources@^1.0.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^3.0.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" + integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== + dependencies: + acorn "^5.0.0" + acorn-dynamic-import "^2.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + async "^2.1.2" + enhanced-resolve "^3.4.0" + escope "^3.6.0" + interpret "^1.0.0" + json-loader "^0.5.4" + json5 "^0.5.1" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + mkdirp "~0.5.0" + node-libs-browser "^2.0.0" + source-map "^0.5.3" + supports-color "^4.2.1" + tapable "^0.2.7" + uglifyjs-webpack-plugin "^0.4.6" + watchpack "^1.4.0" + webpack-sources "^1.0.1" + yargs "^8.0.2" + +webpack@^5.65.0: + version "5.68.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.68.0.tgz#a653a58ed44280062e47257f260117e4be90d560" + integrity sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g== + dependencies: + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.50" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + 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" + +websocket@^1.0.31, websocket@^1.0.32: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + 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" + +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + 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@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which-typed-array@^1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" + integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.7" + +which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.1.5: + version "6.1.5" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.4.6: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + 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" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= + dependencies: + camelcase "^4.1.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + 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" + +yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + 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" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.2.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= + 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" + +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==