diff --git a/.gitignore b/.gitignore index d5b1a3e..da336f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,269 @@ -/**/.DS_Store /**/.vscode /**/spa/**/style.css -/**/node_modules -/**/package-lock.json -/**/npm/dist \ No newline at end of file + +docs/md-build +docs/tmp + +# Created by https://www.toptal.com/developers/gitignore/api/python,solidity,visualstudiocode,react +# Edit at https://www.toptal.com/developers/gitignore?templates=python,solidity,visualstudiocode,react + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +pytestdebug.log + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +doc/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +### react ### +.DS_* +logs +**/*.backup.* +**/*.back.* + +node_modules +bower_components + +*.sublime* + +psd +thumb +sketch + +### Solidity ### +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env.test + +# parcel-bundler cache (https://parceljs.org/) + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.toptal.com/developers/gitignore/api/python,solidity,visualstudiocode,react diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8bcd28b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/build"] + path = docs/build + url = git@github.com:b-u-i-d-l/unifi-docs.git diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2bf0ebc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 100, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false, + "explicitTypes": "always" + } + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d2292da --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing guidelines + +## Table of Contents + +- [Table of Contents](#table-of-contents) +- [Coding Style](#coding-style) + - [Solidity](#solidity) + - [JavaScript](#javascript) + - [Python](#python) +- [Documentation](#documentation) + - [mkdocs](#mkdocs) + +## Coding Style + +### Solidity + +* Solidity portions of the codebase adhere follow the official [Solidity Styleguide] + +### JavaScript + +### Python + +* Python portions of the codebase follow standard PEP8 best practices. +* Python code must be formatted using the Black formatter using the provided settings. + +## Documentation + +New addition to the codebase must be fully documented. + +- JavaScript portions of the code should be annotated using JSDoc style docstrings. +- Solidity portions of the code should be fully annotated using [NatSpec]. + +Documentation is generated using [py-solidity-docgen] and rendered via [mkdocs]. +[py-solidity-docgen] parses NatSpec and outputs `.md` files inside `docs/md-build` according +to a pre-specified Jinja2 template. + +**NOTE:** Each `.sol` file should contain only one `Interface` or `Contract`. + +To build the documentation: + +```console +yarn docs:build +``` + +To serve the documentation + +```console +yarn docs:serve +``` + +### mkdocs + +To install [mkdocs] and [py-solidity-docgen] Python must be installed in the system. + +``` +pip install docs/requirements.in +``` + +**NOTE:** Working inside a virtual environment is highly recommended! + +--- + +[Solidity Styleguide]: https://solidity.readthedocs.io/en/v0.7.0/style-guide.html +[NatSpec]: https://solidity.readthedocs.io/en/v0.7.0/style-guide.html#natspec +[Write the Docs!]: docs/source/write_the_docs.rst +[py-solidity-docgen]: https://github.com/b-u-i-d-l/py-solidity-docgen +[mkdocs]: https://www.mkdocs.org/ diff --git a/README.md b/README.md index c14668c..1fef6b7 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,50 @@ # unifi + +## Table of Contents +- [Table of Contents](#table-of-contents) +- [Decentralized Finance on top of Uniswap, doing fantastic things securely](#decentralized-finance-on-top-of-uniswap-doing-fantastic-thingssecurely) +- [Website: https://unifihub.com](#website-httpsunifihubcom) +- [Unified Stable Dollar](#unified-stabledollar) + - [Example:](#example) + - [Example:](#example-1) + - [Rebalancing](#rebalancing) + - [DFO Debit](#dfo-debit) + - [DFO Credit](#dfo-credit) + - [UniFi has a number of measures in place to ensure uSD's security.](#unifi-has-a-number-of-measures-in-place-to-ensure-usds-security) + - [Resilience, Decentralization and Independence](#resilience-decentralization-and-independence) + - [Allowed Stable Coins](#allowed-stablecoins) + - [APIs and Documentation](#apis-and-documentation) + - [Responsible DeFi Limits](#responsible-defilimits) +- [Craft and Initial Liquidity Offerings (ILOs)](#craft-and-initial-liquidity-offerings-ilos) + - [How Does It Work?](#how-does-it-work) + - [Programmable Liquidity Rules](#programmable-liquidity-rules) + - [Let's play out that aforementioned example.](#lets-play-out-that-aforementioned-example) + - [Initial Liquidity Offering (ILO)](#initial-liquidity-offeringilo) + - [Securing Initial Liquidity for AMMs With Fixed Inflation/Liquidity Staking](#securing-initial-liquidity-for-amms-with-fixed-inflationliquidity-staking) + - [Disarming Sniper Bots](#disarming-sniper-bots) + - [Securing Long Term Locked Investors](#securing-long-term-locked-investors) + - [How ILOs work:](#how-ilos-work) + - [Example](#example-2) +- [UniFi DFO Tax](#unifi-dfo-tax) +- [Releases](#releases) +- [The Bazar](#thebazar) + - [Listing](#listing) + - [Index Funds](#index-funds) + - [Programmable Equities](#programmable-equities) + - [Non-Fungible Tokens (NFTs)](#non-fungible-tokens-nfts) + - [Swappable ERC 1155 Release](#swappable-erc-1155-release) +- [UniFi Token Distribution](#unifi-token-distribution) + - [UniFi Fair Inflation](#unifi-fair-inflation) + - [UniFi Liquidity Staking](#unifi-liquidity-staking) +- [UniFi Earning System](#unifi-earningsystem) + ## Decentralized Finance on top of Uniswap, doing fantastic things securely -### UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap. A DFO protocol powered DeFi set of tools built on top of Uniswap -### Website: https://unifihub.com +UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap. A DFO protocol powered DeFi set of tools built on top of Uniswap + +## Website: https://unifihub.com -# Unified Stable Dollar +## Unified Stable Dollar uSD is a stablecoin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools, and backed by the power of the Unicorn, uSD is the most secure and resilient stablecoin on Ethereum - ever. The only way it could be destabilized is if the entire stablecoin industry crashed. Independent from any off-chain issuer, it is fortified against every risk inherent to all other stablecoins, and free of the anxiety that pervades the industry. @@ -22,13 +62,13 @@ Mint 2x uSD by adding 1x Stablecoin A and 1x Stablecoin B And by burning uSD, an Burn 2x uSD and receive 1x Stablecoin A and 1x Stablecoin C -# Rebalancing +### Rebalancing Sometimes, collateralization is not enough, and uSD must rebalance in one of two ways. -### DFO Debit +#### DFO Debit -When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). +When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). If the stablecoin totally fails, the other stablecoins effectively pump in correlation.DFO Debit resolves this issue on-chain by rebalancing uSD, creating debt which the UniFi DFO then pays off by minting UniFi. Let’s look at how this plays out, step by step: @@ -40,9 +80,9 @@ If the stablecoin totally fails, the other stablecoins effectively pump in corre The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins. -### DFO Credit +#### DFO Credit -As established, uSD is backed by Uniswap stablecoin pools liquidity. +As established, uSD is backed by Uniswap stablecoin pools liquidity. This raises an issue; Uniswap pools earn 0.3% of trading fees. This could destabilize uSD by creating an excess of collateralized stablecoins in the pools.DFO Credit, the second rebalancing function of the UniFi DFO, resolves this by removing that excess from the pools and sending it in the DFO wallet managed by $UniFi holders. @@ -84,7 +124,7 @@ Because we take a Responsible DeFi Approach, UniFi uSD minting is limited in its - 10,000,000 uSD mintable for the first four months (until block n 11541929) - 20,000,000 uSD mintable for the first five months (until block n 11741929) -# Craft and Initial Liquidity Offerings (ILOs) +## Craft and Initial Liquidity Offerings (ILOs) Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely, and with unprecedented security. @@ -98,7 +138,7 @@ The Uniswap protocol allows for liquidity pools composed of 50:50 asset ratios. Anyone can create a Craft order, customize the liquidity setup and deploy it by contributing initial liquidity. Others can then contribute the rest of the liquidity required to pool the order on Uniswap. Later, after the predetermined block, any of the participants can trigger removal of the liquidity. It is then distributed to all participants based on the predetermined rules. -## Programmable Liquidity Rules +### Programmable Liquidity Rules With Crafting, Uniswap liquidity providers can program a liquidity order by customizing the following: @@ -108,7 +148,7 @@ With Crafting, Uniswap liquidity providers can program a liquidity order by cust - Liquidity Ratio: The ratio of liquidity, e.g. 10% DAI - 90% ETH or 0% DAI - 100 ETH. Once deployed by the creator, others can add the required liquidity. If the creator sets the ratio at 10% DAI - 90% ETH, the others can add the rest at 90% DAI - 10% ETH. - Liquidity Exit/Discount: An advanced feature for orders that allows for the creation of a different ratio or even a discount for the exit. -### Let's play out that aforementioned example. +#### Let's play out that aforementioned example. Person A creates an order for USDC - DAI, with a min block length of 543055 Blocks and a ratio of 10% DAI - 90% USDC. He adds 100 DAI and 900 USDC, and also decides to set the exit liquidity at 30% DAI and 70% USDC (read on to see exactly how exit liquidity works). @@ -130,29 +170,29 @@ A receives 600 DAI and 1,400 USDC (at the Exit Ratio of 30% DAI and 70% USDC). Based on how much they individually contributed, B, C and D receive their respective proportion of 1,400 DAI and 600 USDC (at the Exit Ratio of 70% DAI and 30% USDC). -# Initial Liquidity Offering (ILO) +### Initial Liquidity Offering (ILO) ILOs are a way for Ethereum-based startups to configure "Crafting" - i.e, Programmable Liquidity - rules to secure long term funding by providing Uniswap liquidity. ILOs are helpful for three specific reasons: -### Securing Initial Liquidity for AMMs With Fixed Inflation/Liquidity Staking +#### Securing Initial Liquidity for AMMs With Fixed Inflation/Liquidity Staking Providers can offer liquidity with fixed inflation without dumping on new holders. They also help new investors reduce slippage and become holders with a large amount of capital. -### Disarming Sniper Bots +#### Disarming Sniper Bots Sniper Bots track new low liquidity Uniswap pools for sizable capital before liquidity even comes in, making it (until now) impossible for startups to offer liquidity with low collateral. -### Securing Long Term Locked Investors +#### Securing Long Term Locked Investors Investors lock their funds for the long run. -### How ILOs work: +#### How ILOs work: Before distributing their tokens, startups can set crafting orders with fixed pre-values, adding the token and requesting the collateral required to fill the order. Investors provide that collateral, and if the startup chooses, investors get an Exit/Discount to mitigate the high risk. -### Example +##### Example The token creator sets a Crafting order with low liquidity, e.g. 1,000,000 of the token and 1 ETH, with a 90% - 10% ratio, or even 1,000,000 of token and 0 ETH, with a 100% - 0% ratio (adding a pre-value of the token, if the liquidity pool is not open yet) for one year. Setting the Liquidity Exit/Discount 10%/20%, investors will receive at the end of the order 90%/80%. @@ -160,45 +200,45 @@ In this case, investors invest their own Ethereum for a new token that is not al ILOs enable new Ethereum fundraising rules that solve liquidity issues in early stages, while also helping legitimate projects set Fixed Inflation. This empowers projects and investors in the long run.UniFi DFO Tax: -### UniFi DFO Tax +## UniFi DFO Tax The UniFi DFO earns via the Crafting function; 0.1% of the total Uniswap pool tokens in a Craft order is taxed and paid directly when a participant calls the remove function. -### Release +## Releases The release Of Crafting and ILOs is expected for early October 2020. -# The Bazar +## The Bazar Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities and Token Index Funds (and soon NFTs, including ERC1155s, thanks to ethArt V2) can now be swapped on the new Bazar DEX. The UniFi Bazar unleashes the true potential of Decentralized Finance on the top of Uniswap, by enabling Ethereans to trade these more easily than ever before. -## Listing +### Listing -### Index Funds +#### Index Funds Previously, any ERC20 Uniswap V2 pool token could be traded on Uniswap. But Index Funds - backed by multiple ERC20 tokens - could not. Until now. On the Bazar, Ethereans can freely swap and track crypto Index Funds. -### Programmable Equities +#### Programmable Equities Programmable equities are a new asset class in crypto. They are the ERC20 voting tokens of Decentralized Flexible Organizations (DFOs). Holders have 100% ownership of the protocol; there is no opportunity for external manipulation. On the Bazar, all programmable equities can be listed and traded on Uniswap. -### Non-Fungible Tokens (NFTs) +#### Non-Fungible Tokens (NFTs) ERC1155 NFTs are tokens with metadata, but at the same time have a supply. The reason they haven't been tradable in AMMs before is due to their 'transfer' function. They use the 'SafeTransferFrom' method, instead of the ERC20 methods, 'Transfer' and 'TransferFrom.' Also, they don't have decimals; they're transferred using ID and Amount. ethArt V2 will be released in November, and the Bazar will be able to synthesise ERC1155 tokens with ERC20s (as WETH with ETH) in the background, fundamentally reshaping the NFT market by allowing Ethereans to trade ERC1155 tokens for the first time. -### Swappable ERC 1155 Release +#### Swappable ERC 1155 Release The release of ethArt V2 and swappable NFTs is scheduled for late November.  -# UniFi Token Distribution +## UniFi Token Distribution The total supply of $UniFi is 88,888,888, which is initially distributed and Locked as follows: @@ -206,7 +246,7 @@ The total supply of $UniFi is 88,888,888, which is initially distributed and Loc - 40% (35,900,000) are locked in the UniFI's DFO wallet [0x2578aA454b29C15c8eEF62C972Ee1ff57CD99DEf]. This pays out the liquidity staking rewards. The active reward staking contract is [0xb266252Fd70D253b4330151A96694d35e94b846c] - 16% (14,333,333) are locked in the DFOhub wallet (owned by $buidl holders) [0x5D40c724ba3e7Ffa6a91db223368977C522BdACD] -# UniFi Fair Inflation +### UniFi Fair Inflation A sustainable economic model for DFO-based startups to maintain value and fund operations | UniFi version @@ -221,7 +261,7 @@ Inflation events will occur once a day (every 6,300 ETH Blocks) across three Uni All functionalities related to this R&D will become available for every DFO as Optional Basic Functionalities, to accelerate the exploration of Programmable Equity R&D. -# UniFi Liquidity Staking +### UniFi Liquidity Staking $UniFi liquidity staking is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c @@ -231,7 +271,7 @@ Staking will inflate the supply over the first year (if every tier is completely The Five Year tier was filled by the team in an early test, and we won't touch the rewards for three years. When they are unlocked and redeemed, 50% of the UniFi will be sent to the UniFi wallet and 50% to the NERV operations wallet. -# UniFi Earning System +## UniFi Earning System The UniFi DFO earn from: diff --git a/contracts/stableCoin/farming/IUnifiedStableFarming.sol b/contracts/stableCoin/farming/IUnifiedStableFarming.sol index de9ba15..617738f 100644 --- a/contracts/stableCoin/farming/IUnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/IUnifiedStableFarming.sol @@ -1,35 +1,62 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity >=0.7.0 <0.8.0; +/** + * @title UnifiedStableFarming + * @dev Arbitrage helper + */ interface IUnifiedStableFarming { + function percentage() external view returns (uint256[] memory); - function percentage() external view returns(uint256[] memory); - - //Earn pumping uSD - Means swap a chosen stableCoin for uSD, then burn the difference of uSD to obtain a greater uSD value in Uniswap Pool tokens + /** + * @dev Earn by pumping $uSD: Swap stablecoins for $uSD in their pools, then burn $uSD until + * equilibrium. + * @param stableCoinAddress Address of the $uSD stablecoin + * @param pairIndex Index of the pair inside the whitelisted pairs array + * @param pairAmount Amount of Uniswap liquidity tokens to send back to the pool + * @param amountAMin The minimum amount of tokenA that must be received for the transaction not to revert + * @param amountBMin The minimum amount of tokenB that must be received for the transaction not to revert + * @param tokenAddress Address of the token to swap to get $uSD + * @param tokenValue How much to swap for + */ function earnByPump( address stableCoinAddress, uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1, + uint256 amountAMin, + uint256 amountBMin, address tokenAddress, - uint256 tokenValue) external payable; + uint256 tokenValue + ) external payable; - //Earn dumping uSD - Means mint uSD then swap uSD for the chosen Uniswap Pool tokens + /** + * @dev Earn by dumping $uSD: Mint stablecoins obtaining $usd then swap it back for caller choice of + * stablecoins + * @param stableCoinAddress Address of the uSD stablecoin + * @param pairIndex Index of the pair inside the whitelisted pairs array + * @param amountA Amount of tokenA + * @param amountB Amount of tokenB + * @param amountAMin The minimum amount of tokenA that must be received for the transaction not to revert + * @param amountBMin The minimum amount of tokenB that must be received for the transaction not to revert + * @param tokenIndices Array of indices identifying which stablecoins to obtain as result of the + * arbitrage + * @param stableCoinAmounts Array of containing the amounts of stablecoins to get as result of the + * arbitrage + */ function earnByDump( address stableCoinAddress, uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min, + uint256 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin, uint256[] calldata tokenIndices, - uint256[] calldata stableCoinAmounts) external; + uint256[] calldata stableCoinAmounts + ) external; } interface IStableCoin { - function allowedPairs() external view returns (address[] memory); function fromTokenToStable(address tokenAddress, uint256 amount) @@ -55,20 +82,46 @@ interface IStableCoin { interface IUniswapV2Pair { function token0() external view returns (address); + function token1() external view returns (address); } -interface IUniswapV2Router { +interface IUniswapV2Router02 { function WETH() external pure returns (address); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); - function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); + + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + function swapExactTokensForTokens( + uint256 amountIn, + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function swapExactETHForTokens( + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external payable returns (uint256[] memory amounts); } interface IERC20 { function balanceOf(address account) external view returns (uint256); + function transfer(address recipient, uint256 amount) external returns (bool); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); -} \ No newline at end of file + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); +} diff --git a/contracts/stableCoin/farming/UnifiedStableFarming.sol b/contracts/stableCoin/farming/UnifiedStableFarming.sol index 7796c0e..5c005df 100644 --- a/contracts/stableCoin/farming/UnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/UnifiedStableFarming.sol @@ -13,7 +13,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { uint256[] private _percentage; constructor(uint256[] memory percentage) { - WETH_ADDRESS = IUniswapV2Router(UNISWAP_V2_ROUTER).WETH(); + WETH_ADDRESS = IUniswapV2Router02(UNISWAP_V2_ROUTER).WETH(); assert(percentage.length == 2); _percentage = percentage; } @@ -22,49 +22,45 @@ contract UnifiedStableFarming is IUnifiedStableFarming { return _percentage; } - //Earn pumping uSD - Means swap a chosen stableCoin for uSD, then burn the difference of uSD to obtain a greater uSD value in Uniswap Pool tokens + /** + * @inheritdoc IUnifiedStableFarming + */ function earnByPump( address stableCoinAddress, uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1, + uint256 amountAMin, + uint256 amountBMin, address tokenAddress, uint256 tokenValue ) public override payable { - if(tokenAddress != WETH_ADDRESS) { - _transferToMeAndCheckAllowance( - tokenAddress, - tokenValue, - UNISWAP_V2_ROUTER - ); + if (tokenAddress != WETH_ADDRESS) { + _transferToMeAndCheckAllowance(tokenAddress, tokenValue, UNISWAP_V2_ROUTER); } - uint256 realTokenValue = tokenAddress == WETH_ADDRESS - ? msg.value - : tokenValue; - uint256 stableCoinAmount = _swap( - tokenAddress, - stableCoinAddress, - realTokenValue, - address(this) - ); - (uint256 return0, uint256 return1) = IStableCoin(stableCoinAddress) - .burn(pairIndex, pairAmount, amount0, amount1); - (address token0, address token1, ) = _getPairData( - stableCoinAddress, - pairIndex + uint256 realTokenValue = tokenAddress == WETH_ADDRESS ? msg.value : tokenValue; + _swap(tokenAddress, stableCoinAddress, realTokenValue, address(this)); + // Swap stablecoin for $uSD + IStableCoin(stableCoinAddress).burn( + pairIndex, + pairAmount, + amountAMin, + amountBMin ); - _flushToSender(token0, token1, stableCoinAddress, tokenAddress); + (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); + // Send the tokens back to their owner + _flushToSender(tokenA, tokenB, stableCoinAddress, address(0)); } - //Earn dumping uSD - Means mint uSD then swap uSD for the chosen Uniswap Pool tokens + /** + * @inheritdoc IUnifiedStableFarming + */ function earnByDump( address stableCoinAddress, uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min, + uint256 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin, uint256[] memory tokenIndices, uint256[] memory stableCoinAmounts ) public override { @@ -72,46 +68,47 @@ contract UnifiedStableFarming is IUnifiedStableFarming { tokenIndices.length > 0 && tokenIndices.length <= 2, "You must choose at least one of the two Tokens" ); + // If you want N pairs as output there must be N amount specified require( tokenIndices.length == stableCoinAmounts.length, "Token Indices and StableCoin Amounts must have the same length" ); - (address token0, address token1) = _prepareForDump( + (address tokenA, address tokenB) = _prepareForDump( stableCoinAddress, pairIndex, - amount0, - amount1 + amountA, + amountB ); + // Mint $uSD IStableCoin(stableCoinAddress).mint( pairIndex, - amount0, - amount1, - amount0Min, - amount1Min + amountA, + amountB, + amountAMin, + amountBMin ); + // For each of the chosen output pair swap $uSD to obtain the desired amount of stablecoin for (uint256 i = 0; i < tokenIndices.length; i++) { _swap( stableCoinAddress, - tokenIndices[i] == 0 ? token0 : token1, + tokenIndices[i] == 0 ? tokenA : tokenB, stableCoinAmounts[i], msg.sender ); } - _flushToSender(token0, token1, stableCoinAddress, address(0)); + // Send the tokens back to their owner + _flushToSender(tokenA, tokenB, stableCoinAddress, address(0)); } function _transferTokens( address stableCoinAddress, uint256 pairIndex, - uint256 amount0, - uint256 amount1 + uint256 amountA, + uint256 amountB ) private { - (address token0, address token1, ) = _getPairData( - stableCoinAddress, - pairIndex - ); - IERC20(token0).transferFrom(msg.sender, address(this), amount0); - IERC20(token1).transferFrom(msg.sender, address(this), amount1); + (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); + IERC20(tokenA).transferFrom(msg.sender, address(this), amountA); + IERC20(tokenB).transferFrom(msg.sender, address(this), amountB); } function _getPairData(address stableCoinAddress, uint256 pairIndex) @@ -124,8 +121,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { ) { IUniswapV2Pair pair = IUniswapV2Pair( - pairAddress = IStableCoin(stableCoinAddress) - .allowedPairs()[pairIndex] + pairAddress = IStableCoin(stableCoinAddress).allowedPairs()[pairIndex] ); token0 = pair.token0(); token1 = pair.token1(); @@ -142,6 +138,9 @@ contract UnifiedStableFarming is IUnifiedStableFarming { } } + /** + * @dev Transfer token to the smart contract + */ function _transferToMeAndCheckAllowance( address tokenAddress, uint256 value, @@ -163,22 +162,25 @@ contract UnifiedStableFarming is IUnifiedStableFarming { } function _flushToSender( - address token0, - address token1, - address token2, - address token3 + address tokenA, + address tokenB, + address tokenC, + address tokenD ) private { - _flushToSender(token0); - _flushToSender(token1); - _flushToSender(token2); - _flushToSender(token3); + _flushToSender(tokenA); + _flushToSender(tokenB); + _flushToSender(tokenC); + _flushToSender(tokenD); } + /** + * @dev Send token to the address calling this contract + */ function _flushToSender(address tokenAddress) private { if (tokenAddress == address(0)) { return; } - if(tokenAddress == WETH_ADDRESS) { + if (tokenAddress == WETH_ADDRESS) { payable(msg.sender).transfer(address(this).balance); return; } @@ -189,6 +191,13 @@ contract UnifiedStableFarming is IUnifiedStableFarming { } } + /** + * @dev Swap on uniswap! + * @param tokenIn Address of the input token + * @param tokenOut Address of the output token + * @param amountIn Amount to swap + * @param receiver Address of the receiver of the swap (who gets the money) + */ function _swap( address tokenIn, address tokenOut, @@ -197,14 +206,14 @@ contract UnifiedStableFarming is IUnifiedStableFarming { ) private returns (uint256) { _checkAllowance(tokenIn, amountIn, UNISWAP_V2_ROUTER); - IUniswapV2Router uniswapV2Router = IUniswapV2Router(UNISWAP_V2_ROUTER); + IUniswapV2Router02 uniswapV2Router = IUniswapV2Router02(UNISWAP_V2_ROUTER); address[] memory path = new address[](2); path[0] = tokenIn; path[1] = tokenOut; if (path[0] == WETH_ADDRESS) { return - uniswapV2Router.swapExactETHForTokens{value: amountIn}( + uniswapV2Router.swapExactETHForTokens{ value: amountIn }( uniswapV2Router.getAmountsOut(amountIn, path)[1], path, receiver, diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol similarity index 53% rename from contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol rename to contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol index 0a88b6f..20504a0 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,41 +1,60 @@ -/* Discussion: - * https://github.com/b-u-i-d-l/unifi - */ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0 <0.8.0; + /* Description: * When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). If the stablecoin totally fails, the other stablecoins effectively pump in correlation. - * + * * DFO Debit resolves this issue on-chain by rebalancing uSD, creating debt which the UniFi DFO then pays off by minting UniFi. Let’s look at how this plays out, step by step: - * + * * 1 - A stablecoin collateralized by uSD loses value or fails altogether. - * + * * 2 - $UniFi holders vote to remove the tiers containing the failed stablecoin from the whitelist.The uSD supply becomes grater than the supply of the collateralized pooled stablecoins. - * + * * 3 - To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio. - * + * * The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins. */ -// SPDX-License-Identifier: MIT - -pragma solidity 0.7.0; +/** + * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) + * @dev This contract adds unifi minting capabilities to uSD + */ contract MintNewVotingTokensForStableCoinFunctionality { - function onStart(address, address) public { - IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); + IStateHolder stateHolder = IStateHolder( + IMVDProxy(msg.sender).getStateHolderAddress() + ); address stablecoinauthorized = 0x44086035439E676c02D411880FcCb9837CE37c57; - stateHolder.setBool(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized)), true); + stateHolder.setBool( + _toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized)), + true + ); } function onStop(address) public { - IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); + IStateHolder stateHolder = IStateHolder( + IMVDProxy(msg.sender).getStateHolderAddress() + ); address stablecoinauthorized = 0x44086035439E676c02D411880FcCb9837CE37c57; - stateHolder.clear(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized))); + stateHolder.clear( + _toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized)) + ); } - function mintNewVotingTokensForStableCoin(address sender, uint256, uint256 amountToMint, address receiver) public { + function mintNewVotingTokensForStableCoin( + address sender, + uint256, + uint256 amountToMint, + address receiver + ) public { IMVDProxy proxy = IMVDProxy(msg.sender); - require(IStateHolder(proxy.getStateHolderAddress()).getBool(_toStateHolderKey("stablecoin.authorized", _toString(sender))), "Unauthorized action!"); + require( + IStateHolder(proxy.getStateHolderAddress()).getBool( + _toStateHolderKey("stablecoin.authorized", _toString(sender)) + ), + "Unauthorized action!" + ); IERC20 token = IERC20(proxy.getToken()); uint256 proxyBalanceOf = token.balanceOf(address(proxy)); @@ -45,57 +64,83 @@ contract MintNewVotingTokensForStableCoinFunctionality { proxy.transfer(receiver, amountToMint, address(token)); - if(proxyBalanceOf > 0) { + if (proxyBalanceOf > 0) { proxy.transfer(address(proxy), proxyBalanceOf, address(token)); } } - function _toStateHolderKey(string memory a, string memory b) private pure returns(string memory) { + function _toStateHolderKey(string memory a, string memory b) + private + pure + returns (string memory) + { return _toLowerCase(string(abi.encodePacked(a, "_", b))); } - function _toString(address _addr) private pure returns(string memory) { + function _toString(address _addr) private pure returns (string memory) { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = "0123456789abcdef"; bytes memory str = new bytes(42); - str[0] = '0'; - str[1] = 'x'; - for (uint i = 0; i < 20; i++) { - str[2+i*2] = alphabet[uint(uint8(value[i + 12] >> 4))]; - str[3+i*2] = alphabet[uint(uint8(value[i + 12] & 0x0f))]; + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint256(uint8(value[i + 12] >> 4))]; + str[3 + i * 2] = alphabet[uint256(uint8(value[i + 12] & 0x0f))]; } return string(str); } - function _toLowerCase(string memory str) private pure returns(string memory) { + function _toLowerCase(string memory str) private pure returns (string memory) { bytes memory bStr = bytes(str); - for (uint i = 0; i < bStr.length; i++) { - bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i]; + for (uint256 i = 0; i < bStr.length; i++) { + bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A + ? bytes1(uint8(bStr[i]) + 0x20) + : bStr[i]; } return string(bStr); } } interface IMVDProxy { - function getToken() external view returns(address); - function getStateHolderAddress() external view returns(address); - function getMVDFunctionalitiesManagerAddress() external view returns(address); - function transfer(address receiver, uint256 value, address token) external; - function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) external; + function getToken() external view returns (address); + + function getStateHolderAddress() external view returns (address); + + function getMVDFunctionalitiesManagerAddress() external view returns (address); + + function transfer( + address receiver, + uint256 value, + address token + ) external; + + function flushToWallet( + address tokenAddress, + bool is721, + uint256 tokenId + ) external; } interface IMVDFunctionalitiesManager { - function isAuthorizedFunctionality(address functionality) external view returns(bool); + function isAuthorizedFunctionality(address functionality) + external + view + returns (bool); } interface IStateHolder { - function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal); - function setBool(string calldata varName, bool val) external returns(bool); + function clear(string calldata varName) + external + returns (string memory oldDataType, bytes memory oldVal); + + function setBool(string calldata varName, bool val) external returns (bool); + function getBool(string calldata varName) external view returns (bool); } interface IERC20 { function mint(uint256 amount) external; + function balanceOf(address account) external view returns (uint256); -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 7d4039b..c14b4d8 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -1,8 +1,29 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.7.0; - -interface IStableCoin { +import "./IERC20.sol"; + +/** + * @title Interface for the $uSD aka unified Stable Dollar. + * @dev Define the interface for the $usD + * + * The core idea behind Unified Stable Coin is to implement a stable coin collateralized by pools of whitelisted + * stable coins on UniSwap. By hedging across several pools and implementing simple yet effective + * rebalancing schemes, $uSD is able reduce an holder exposure to a stable-coin failure. + * + */ +interface IStableCoin is IERC20 { + /** + * Initialize the StableCoin. + * @dev Constructor signature + * @param name name of the StableCoin ERC20 token + * @param symbol ticker for the StableCoin ERC20 token + * @param doubleProxy address for the DoubleProxy + * @param allowedPairs array of Uniswap Pairs to be set as whitelisted source tokens + * @param rebalanceRewardMultiplier multiplier used to compute how many unifi tokens to mint during $uSD rebalance + * @param timeWindows time windows inside which some time-delimited operations can be performed + * @param mintables max amount of mintables inside a timeWindow + */ function init( string calldata name, string calldata symbol, @@ -13,58 +34,143 @@ interface IStableCoin { uint256[] calldata mintables ) external; - function tierData() external view returns(uint256[] memory, uint256[] memory); + // |------------------------------------------------------------------------------------------| + // | ----- GETTERS ----- | + // |------------------------------------------------------------------------------------------| - function availableToMint() external view returns(uint256); + /** + * @return Array of allowed Uniswap pairs + */ + function allowedPairs() external view returns (address[] memory); - function doubleProxy() external view returns (address); + /** + * @return mintable The amount of available mintable token + */ + function availableToMint() external view returns (uint256 mintable); - function setDoubleProxy(address newDoubleProxy) external; + // DOCUMENT + function differences() external view returns (uint256, uint256); - function allowedPairs() external view returns (address[] memory); + /** + * @return The address for the doubleProxy smart contract + */ + function doubleProxy() external view returns (address); - function setAllowedPairs(address[] calldata newAllowedPairs) external; + /** + * @return The multiplier used to compute the rebalancing rewards + */ + function rebalanceRewardMultiplier() external view returns (uint256[] memory); - function rebalanceRewardMultiplier() - external - view - returns (uint256[] memory); + /** + * @return All tiers of data of the carried context + */ + function tierData() external view returns (uint256[] memory, uint256[] memory); - function differences() external view returns (uint256, uint256); + // |------------------------------------------------------------------------------------------| + // | ----- SETTERS ----- | + // |------------------------------------------------------------------------------------------| - function calculateRebalanceByDebtReward(uint256 burnt) - external - view - returns (uint256); + /** + * @param newAllowedPairs list of Uniswap pairs to be whitelisted + */ + function setAllowedPairs(address[] calldata newAllowedPairs) external; + + /** + * @param newDoubleProxy new DoubleProxy to set + */ + function setDoubleProxy(address newDoubleProxy) external; + // |------------------------------------------------------------------------------------------| + // | ----- CORE FUNCTIONS ----- | + // |------------------------------------------------------------------------------------------| + + /** + * @dev Compute the reward of the rebalanceByDebt() operation. + * + * @param burnt amount of of $uSD burnt + */ + function calculateRebalanceByDebtReward(uint256 burnt) external view returns (uint256 reward); + + /** + * @dev Convert from one of the allowed whitelisted tokens to $uSD + * + * @param tokenAddress Address of the token to convert + * @param amount Amount of Unifi token to be converted + * + * @return Amount of $uSD tokens + */ function fromTokenToStable(address tokenAddress, uint256 amount) external view returns (uint256); + /** + * Mint logic of the StableCoin. + * @dev Mint the $uSD token + * + * @param pairIndex Index of the pair inside the allowedPairs array + * @param amountA The amount of tokenA to add as liquidity if the B/A price is <= + * amountBDesired/amountADesired (A depreciates) + * @param amountB The amount of tokenB to add as liquidity if the A/B price is <= + * amountADesired/amountBDesired (B depreciates) + * @param amountAMin Bounds the extent to which the B/A price can go up before the transaction reverts. + * Must be <= amountADesired + * @param amountBMin Bounds the extent to which the A/B price can go up before the transaction reverts. + * Must be <= amountBDesired + * + * @return minted Amount of freshly minted $uSD token + */ function mint( uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min - ) external returns (uint256); - + uint256 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin + ) external returns (uint256 minted); + + /** + * Burn logic of the StableCoin. + * @dev Burn the $uSD token + * + * @param pairIndex Index of the pair inside the allowedPairs array + * @param pairAmount Amount of Uniswap liquidity tokens to send back to the pool + * @param amountAMin The minimum amount of tokenA that must be received for the transaction not to revert + * @param amountBMin The minimum amount of tokenB that must be received for the transaction not to revert + * + * @return removedA The amount of tokenA received + * @return removedB The amount of tokenB received + * + */ function burn( uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1 - ) external returns (uint256, uint256); - + uint256 amountAMin, + uint256 amountBMin + ) external returns (uint256 removedA, uint256 removedB); + + /** + * @dev Rebalance by Credit is triggered when the total amount of source tokens' is greater + * than $uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. + * + * @notice Positive imbalances can be caused by the accrual of liquidity provider fee. Withdrawn tokens + * are stored inside the Unifi DFO as a source of long-term value + */ function rebalanceByCredit( uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1 - ) external returns (uint256); - - function rebalanceByDebt(uint256 amount) external returns(uint256); + uint256 amountA, + uint256 amountB + ) external returns (uint256 redeemed); + + /** + * @dev Rebalance by Debt is triggered when the total amount of source tokens' is lesser + * than $uSD circulating supply. Rebalancing is done by minting new equity ($unifi) at premium + * in exchange for burning $uSD. + * + * @notice Negative imbalances can be caused by the failure of a Stable Coin in one of the whitelisted + * source pairs. + */ + function rebalanceByDebt(uint256 amount) external returns (uint256); } interface IDoubleProxy { @@ -74,10 +180,7 @@ interface IDoubleProxy { interface IMVDProxy { function getToken() external view returns (address); - function getMVDFunctionalitiesManagerAddress() - external - view - returns (address); + function getMVDFunctionalitiesManagerAddress() external view returns (address); function getMVDWalletAddress() external view returns (address); @@ -90,18 +193,16 @@ interface IMVDProxy { } interface IMVDFunctionalitiesManager { - function isAuthorizedFunctionality(address functionality) - external - view - returns (bool); + function isAuthorizedFunctionality(address functionality) external view returns (bool); } interface IStateHolder { function getBool(string calldata varName) external view returns (bool); + function getUint256(string calldata varName) external view returns (uint256); } -interface IUniswapV2Router { +interface IUniswapV2Router02 { function getAmountsOut(uint256 amountIn, address[] calldata path) external view @@ -154,4 +255,4 @@ interface IUniswapV2Pair { uint112 reserve1, uint32 blockTimestampLast ); -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 3098384..e787afc 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -5,7 +5,16 @@ pragma solidity ^0.7.0; import "./ERC20.sol"; import "./IStableCoin.sol"; +/** + * @title StableCoin + * @dev Contract for the $uSD Stable Coin. + * It's an ERC20 token extended with the IStableCoin interface and DFO protocol magic. + */ contract StableCoin is ERC20, IStableCoin { + // |------------------------------------------------------------------------------------------| + // | ----- ATTRIBUTES ----- | + // |------------------------------------------------------------------------------------------| + address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; @@ -21,6 +30,13 @@ contract StableCoin is ERC20, IStableCoin { uint256 private _lastRedeemBlock; + // |------------------------------------------------------------------------------------------| + // | ----- CONSTRUCTOR ----- | + // |------------------------------------------------------------------------------------------| + + /** + * @dev Contract constructor. See StableCoin.init() docs. + */ constructor( string memory name, string memory symbol, @@ -44,6 +60,10 @@ contract StableCoin is ERC20, IStableCoin { ); } + /** + * Initialize the StableCoin. + * @inheritdoc IStableCoin + */ function init( string memory name, string memory symbol, @@ -63,20 +83,28 @@ contract StableCoin is ERC20, IStableCoin { _mintables = mintables; } - function tierData() - public - override - view - returns (uint256[] memory, uint256[] memory) - { - return (_timeWindows, _mintables); + // |------------------------------------------------------------------------------------------| + // | ----- GETTERS ----- | + // |------------------------------------------------------------------------------------------| + + /** + * @inheritdoc IStableCoin + */ + function allowedPairs() public override view returns (address[] memory) { + return _allowedPairs; } + /** + * @inheritdoc IStableCoin + */ function availableToMint() public override view returns (uint256) { - uint256 mintable + uint256 mintable = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - if(_timeWindows.length > 0 && block.number < _timeWindows[_timeWindows.length - 1]) { + if ( + _timeWindows.length > 0 && + block.number < _timeWindows[_timeWindows.length - 1] + ) { for (uint256 i = 0; i < _timeWindows.length; i++) { if (block.number < _timeWindows[i]) { mintable = _mintables[i]; @@ -88,22 +116,53 @@ contract StableCoin is ERC20, IStableCoin { return minted >= mintable ? 0 : mintable - minted; } + /** + * @inheritdoc IStableCoin + */ + function differences() public override view returns (uint256 credit, uint256 debt) { + uint256 totalSupply = totalSupply(); + uint256 effectiveAmount = 0; + for (uint256 i = 0; i < _allowedPairs.length; i++) { + (uint256 amount0, uint256 amount1) = _getPairAmount(i); + effectiveAmount += (amount0 + amount1); + } + credit = effectiveAmount > totalSupply ? effectiveAmount - totalSupply : 0; + debt = totalSupply > effectiveAmount ? totalSupply - effectiveAmount : 0; + } + + /** + * @inheritdoc IStableCoin + */ function doubleProxy() public override view returns (address) { return _doubleProxy; } - function setDoubleProxy(address newDoubleProxy) + /** + * @inheritdoc IStableCoin + */ + function rebalanceRewardMultiplier() public override view returns (uint256[] memory) { + return _rebalanceRewardMultiplier; + } + + /** + * @inheritdoc IStableCoin + */ + function tierData() public override - _byCommunity + view + returns (uint256[] memory, uint256[] memory) { - _doubleProxy = newDoubleProxy; + return (_timeWindows, _mintables); } - function allowedPairs() public override view returns (address[] memory) { - return _allowedPairs; - } + // |------------------------------------------------------------------------------------------| + // | ----- SETTERS ----- | + // |------------------------------------------------------------------------------------------| + /** + * @inheritdoc IStableCoin + */ function setAllowedPairs(address[] memory newAllowedPairs) public override @@ -112,56 +171,39 @@ contract StableCoin is ERC20, IStableCoin { _allowedPairs = newAllowedPairs; } - function rebalanceRewardMultiplier() - public - override - view - returns (uint256[] memory) - { - return _rebalanceRewardMultiplier; + /** + * @inheritdoc IStableCoin + */ + function setDoubleProxy(address newDoubleProxy) public override _byCommunity { + _doubleProxy = newDoubleProxy; } - function differences() - public - override - view - returns (uint256 credit, uint256 debt) - { - uint256 totalSupply = totalSupply(); - uint256 effectiveAmount = 0; - for (uint256 i = 0; i < _allowedPairs.length; i++) { - (uint256 amount0, uint256 amount1) = _getPairAmount(i); - effectiveAmount += (amount0 + amount1); - } - credit = effectiveAmount > totalSupply - ? effectiveAmount - totalSupply - : 0; - debt = totalSupply > effectiveAmount - ? totalSupply - effectiveAmount - : 0; - } + // |------------------------------------------------------------------------------------------| + // | ----- CORE FUNCTIONS ----- | + // |------------------------------------------------------------------------------------------| + /** + * @inheritdoc IStableCoin + */ function calculateRebalanceByDebtReward(uint256 burnt) public override view returns (uint256 reward) { - if(burnt == 0) { + if (burnt == 0) { return 0; } address[] memory path = new address[](2); path[0] = address(this); path[1] = IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getToken(); - reward = IUniswapV2Router(UNISWAP_V2_ROUTER).getAmountsOut( - burnt, - path - )[1]; - reward = - (reward * _rebalanceRewardMultiplier[0]) / - _rebalanceRewardMultiplier[1]; + reward = IUniswapV2Router02(UNISWAP_V2_ROUTER).getAmountsOut(burnt, path)[1]; + reward = (reward * _rebalanceRewardMultiplier[0]) / _rebalanceRewardMultiplier[1]; } + /** + * @inheritdoc IStableCoin + */ function fromTokenToStable(address tokenAddress, uint256 amount) public override @@ -177,113 +219,132 @@ contract StableCoin is ERC20, IStableCoin { return result * 10**remainingDecimals; } + /** + * @inheritdoc IStableCoin + * + * @dev Minting first check tha DFO auth protocol are respected, secondly it sends the tokens + * to a Uniswap Pool (_createPoolToken) + * + */ function mint( uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min + uint256 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin ) public override _forAllowedPair(pairIndex) returns (uint256 minted) { + // NOTE: Use DFO protocol to check for authorization require( IStateHolder( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) - .getStateHolderAddress() + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress() ) .getBool( - _toStateHolderKey( - "stablecoin.authorized", - _toString(address(this)) - ) + _toStateHolderKey("stablecoin.authorized", _toString(address(this))) ), "Unauthorized action!" ); - (address token0, address token1, ) = _getPairData(pairIndex); - _transferTokensAndCheckAllowance(token0, amount0); - _transferTokensAndCheckAllowance(token1, amount1); + (address tokenA, address tokenB, ) = _getPairData(pairIndex); + _transferTokensAndCheckAllowance(tokenA, amountA); + _transferTokensAndCheckAllowance(tokenB, amountB); (uint256 firstAmount, uint256 secondAmount, ) = _createPoolToken( - token0, - token1, - amount0, - amount1, - amount0Min, - amount1Min + tokenA, + tokenB, + amountA, + amountB, + amountAMin, + amountBMin ); minted = - fromTokenToStable(token0, firstAmount) + - fromTokenToStable(token1, secondAmount); - require(minted <= availableToMint(), "Minting amount is greater than availability"); + fromTokenToStable(tokenA, firstAmount) + + fromTokenToStable(tokenB, secondAmount); + require( + minted <= availableToMint(), + "Minting amount is greater than availability!" + ); _mint(msg.sender, minted); } + /** + * @inheritdoc IStableCoin + * @dev Burn $usd to get back stablecoins from the pools + */ function burn( uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1 + uint256 amountAMin, + uint256 amountBMin ) public override _forAllowedPair(pairIndex) - returns (uint256 removed0, uint256 removed1) + returns (uint256 removedA, uint256 removedB) { - (address token0, address token1, address pairAddress) = _getPairData(pairIndex); + (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); - (removed0, removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER) - .removeLiquidity( - token0, - token1, + // Remove pooled stablecoins + (removedA, removedB) = IUniswapV2Router02(UNISWAP_V2_ROUTER).removeLiquidity( + tokenA, + tokenB, pairAmount, - amount0, - amount1, + amountAMin, + amountBMin, msg.sender, block.timestamp + 1000 ); + // Actually burn the $uSD _burn( msg.sender, - fromTokenToStable(token0, removed0) + - fromTokenToStable(token1, removed1) + fromTokenToStable(tokenA, removedA) + fromTokenToStable(tokenB, removedB) ); } + /** + * @dev Rebalance by Credit is triggered when the total amount of source tokens is greater + * than uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. + * + * @inheritdoc IStableCoin + */ function rebalanceByCredit( uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1 + uint256 amountA, + uint256 amountB ) public override _forAllowedPair(pairIndex) returns (uint256 redeemed) { + // NOTE: Use DFO Protocol to check for authorization require( block.number >= - _lastRedeemBlock + - IStateHolder( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) - .getStateHolderAddress() - ) - .getUint256("stablecoin.rebalancebycredit.block.interval"), + _lastRedeemBlock + + IStateHolder( + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) + .getStateHolderAddress() + ) + .getUint256("stablecoin.rebalancebycredit.block.interval"), "Unauthorized action!" ); _lastRedeemBlock = block.number; (uint256 credit, ) = differences(); - (address token0, address token1, address pairAddress) = _getPairData(pairIndex); + (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); - (uint256 removed0, uint256 removed1) = IUniswapV2Router( - UNISWAP_V2_ROUTER - ) + (uint256 removed0, uint256 removed1) = IUniswapV2Router02(UNISWAP_V2_ROUTER) .removeLiquidity( - token0, - token1, + tokenA, + tokenB, pairAmount, - amount0, - amount1, + amountA, + amountB, IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDWalletAddress(), block.timestamp + 1000 ); redeemed = - fromTokenToStable(token0, removed0) + - fromTokenToStable(token1, removed1); + fromTokenToStable(tokenA, removed0) + + fromTokenToStable(tokenB, removed1); require(redeemed <= credit, "Cannot redeem given pair amount"); } - function rebalanceByDebt(uint256 amount) public override returns(uint256 reward) { + /** + * @inheritdoc IStableCoin + */ + function rebalanceByDebt(uint256 amount) public override returns (uint256 reward) { require(amount > 0, "You must insert a positive value"); (, uint256 debt) = differences(); require(amount <= debt, "Cannot Burn this amount"); @@ -299,6 +360,11 @@ contract StableCoin is ERC20, IStableCoin { ); } + // -------------------------------------------------------------------------------------------| + + /** + * // DOCUMENT + */ modifier _byCommunity() { require( IMVDFunctionalitiesManager( @@ -311,14 +377,19 @@ contract StableCoin is ERC20, IStableCoin { _; } + /** + * // DOCUMENT + */ modifier _forAllowedPair(uint256 pairIndex) { - require( - pairIndex >= 0 && pairIndex < _allowedPairs.length, - "Unknown pair!" - ); + require(pairIndex >= 0 && pairIndex < _allowedPairs.length, "Unknown pair!"); _; } + // -------------------------------------------------------------------------------------------| + + /** + * // DOCUMENT + */ function _getPairData(uint256 pairIndex) private view @@ -328,21 +399,24 @@ contract StableCoin is ERC20, IStableCoin { address pairAddress ) { - IUniswapV2Pair pair = IUniswapV2Pair( - pairAddress = _allowedPairs[pairIndex] - ); + IUniswapV2Pair pair = IUniswapV2Pair(pairAddress = _allowedPairs[pairIndex]); token0 = pair.token0(); token1 = pair.token1(); } - function _transferTokensAndCheckAllowance( - address tokenAddress, - uint256 value - ) private { + /** + * // DOCUMENT + */ + function _transferTokensAndCheckAllowance(address tokenAddress, uint256 value) + private + { IERC20(tokenAddress).transferFrom(msg.sender, address(this), value); _checkAllowance(tokenAddress, value); } + /** + * // DOCUMENT + */ function _checkAllowance(address tokenAddress, uint256 value) private { IERC20 token = IERC20(tokenAddress); if (token.allowance(address(this), UNISWAP_V2_ROUTER) <= value) { @@ -353,48 +427,61 @@ contract StableCoin is ERC20, IStableCoin { } } + /** + * @dev Utility Function: Use the Uniswap Router to add liquidity to a pool. + * + * @param tokenA A pool token + * @param tokenB A pool token + * @param liquidity The amount of liquidity tokens to remove + * @param amountADesired The amount of tokenA to add as liquidity if the B/A price is <= + * amountBDesired/amountADesired (A depreciates). + * @param amountBDesired The amount of tokenB to add as liquidity if the A/B price is <= + * amountADesired/amountBDesired (B depreciates). + * @param amountAMin Bounds the extent to which the B/A price can go up before the transaction reverts. Must be <= amountADesired. + * @param amountBMin Bounds the extent to which the A/B price can go up before the transaction reverts. Must be <= amountBDesired. + * + * @return amountA The amount of tokenA sent to the pool + * @return amountB The amount of tokenB sent to the pool + * @return liquidity The amount of liquidity tokens minted + * + */ function _createPoolToken( - address firstToken, - address secondToken, - uint256 originalFirstAmount, - uint256 originalSecondAmount, - uint256 firstAmountMin, - uint256 secondAmountMin + address tokenA, + address tokenB, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin ) private returns ( - uint256 firstAmount, - uint256 secondAmount, - uint256 poolAmount + uint256 amountA, + uint256 amountB, + uint256 liquidity ) { - (firstAmount, secondAmount, poolAmount) = IUniswapV2Router( - UNISWAP_V2_ROUTER - ) + (amountA, amountB, liquidity) = IUniswapV2Router02(UNISWAP_V2_ROUTER) .addLiquidity( - firstToken, - secondToken, - originalFirstAmount, - originalSecondAmount, - firstAmountMin, - secondAmountMin, + tokenA, + tokenB, + amountADesired, + amountBDesired, + amountAMin, + amountBMin, address(this), block.timestamp + 1000 ); - if (firstAmount < originalFirstAmount) { - IERC20(firstToken).transfer( - msg.sender, - originalFirstAmount - firstAmount - ); + if (amountA < amountADesired) { + IERC20(tokenA).transfer(msg.sender, amountADesired - amountA); } - if (secondAmount < originalSecondAmount) { - IERC20(secondToken).transfer( - msg.sender, - originalSecondAmount - secondAmount - ); + if (amountB < amountBDesired) { + IERC20(tokenB).transfer(msg.sender, amountBDesired - amountB); } } + /** + * // DOCUMENT + */ function _getPairAmount(uint256 i) private view @@ -405,16 +492,13 @@ contract StableCoin is ERC20, IStableCoin { uint256 pairAmount = pair.balanceOf(address(this)); uint256 pairTotalSupply = pair.totalSupply(); (amount0, amount1, ) = pair.getReserves(); - amount0 = fromTokenToStable( - token0, - (pairAmount * amount0) / pairTotalSupply - ); - amount1 = fromTokenToStable( - token1, - (pairAmount * amount1) / pairTotalSupply - ); + amount0 = fromTokenToStable(token0, (pairAmount * amount0) / pairTotalSupply); + amount1 = fromTokenToStable(token1, (pairAmount * amount1) / pairTotalSupply); } + /** + * // DOCUMENT + */ function _toStateHolderKey(string memory a, string memory b) private pure @@ -423,6 +507,9 @@ contract StableCoin is ERC20, IStableCoin { return _toLowerCase(string(abi.encodePacked(a, "_", b))); } + /** + * // DOCUMENT + */ function _toString(address _addr) private pure returns (string memory) { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = "0123456789abcdef"; @@ -437,11 +524,10 @@ contract StableCoin is ERC20, IStableCoin { return string(str); } - function _toLowerCase(string memory str) - private - pure - returns (string memory) - { + /** + * // DOCUMENT + */ + function _toLowerCase(string memory str) private pure returns (string memory) { bytes memory bStr = bytes(str); for (uint256 i = 0; i < bStr.length; i++) { bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A @@ -450,4 +536,4 @@ contract StableCoin is ERC20, IStableCoin { } return string(bStr); } -} \ No newline at end of file +} diff --git a/docs/build b/docs/build new file mode 160000 index 0000000..f49a677 --- /dev/null +++ b/docs/build @@ -0,0 +1 @@ +Subproject commit f49a677c1e5e1ef9bb6b4ca1ef65ff664d1710b5 diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 0000000..1eb8487 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,26 @@ +site_name: Unifi Docs +docs_dir: md-build +site_dir: build +permalink: True +nav: + - Home: README.md + - Contributing: CONTRIBUTING.md + - API: + - Stable Coin: + - IDoubleProxy: stableCoin/standalone/IDoubleProxy.md + - IMVDFunctionalitiesManager: stableCoin/standalone/IMVDFunctionalitiesManager.md + - IMVDProxy: stableCoin/standalone/IMVDProxy.md + - IStateHolder: stableCoin/standalone/IStateHolder.md + - IStableCoin: stableCoin/standalone/IStableCoin.md + - Farming: + - IUnifiedStableFarming: stableCoin/farming/IUnifiedStableFarming.md + - Microservices: + - MintNewVotingTokensForStableCoinFunctionality: stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.md + +theme: + name: readthedocs + highlightjs: true + hljs_languages: + - yaml + - typescript + - javascript diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 0000000..016bb16 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1 @@ +mkdocs diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..d9819f7 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,21 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +click==7.1.2 # via mkdocs, nltk +future==0.18.2 # via lunr +jinja2==2.11.2 # via mkdocs +joblib==0.16.0 # via nltk +livereload==2.6.3 # via mkdocs +lunr[languages]==0.5.8 # via mkdocs +markdown==3.2.2 # via mkdocs +markupsafe==1.1.1 # via jinja2 +mkdocs==1.1.2 # via -r requirements.in +nltk==3.5 # via lunr +pyyaml==5.3.1 # via mkdocs +regex==2020.7.14 # via nltk +six==1.15.0 # via livereload, lunr +tornado==6.0.4 # via livereload, mkdocs +tqdm==4.48.2 # via nltk diff --git a/docs/solidity-docgen-templates/contract.hbs b/docs/solidity-docgen-templates/contract.hbs new file mode 100644 index 0000000..364cddd --- /dev/null +++ b/docs/solidity-docgen-templates/contract.hbs @@ -0,0 +1,55 @@ +# {{name}} + +{{{natspec.devdoc}}} + +{{#if ownFunctions}} +## Functions: +{{#ownFunctions}} +{{#if (or (eq visibility "public") (eq visibility "external"))}} +- [`{{name}}({{args}})`](#function-{{name}}) +{{/if}} +{{/ownFunctions}} +{{/if}} + +{{#if ownEvents}} +## Events: +{{#ownEvents}} +- [`{{name}}({{args}})`](#event-{{name}}) +{{/ownEvents}} +{{/if}} + +{{#ownFunctions}} +{{#if (or (eq visibility "public") (eq visibility "external"))}} +### Function: {{name}} +`{{name}}({{args}}){{#if outputs}} → {{outputs}}{{/if}}` +{{#if natspec.devdoc}} +#### Description +{{natspec.devdoc}}{{else}}{{/if}} +{{#if natspec.params}} +#### Parameters: +{{#natspec.params}} +- `{{param}}`: {{description}} +{{/natspec.params}} +{{/if}} +{{#if natspec.returns}} +#### Return Values: +{{#natspec.returns}} +- {{param}} {{description}} +{{/natspec.returns}} +{{/if}} +{{/if}} +{{/ownFunctions}} + +{{#ownEvents}} +### Event: {{name}} +`{{name}}({{args}})` +{{#if natspec.devdoc}} +#### Description +{{natspec.devdoc}}{{else}}{{/if}} +{{#if natspec.params}} +#### Parameters: +{{#natspec.params}} +- `{{param}}`: {{description}} +{{/natspec.params}} +{{/if}} +{{/ownEvents}} diff --git a/package.json b/package.json new file mode 100644 index 0000000..038d2a9 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "unifi", + "version": "0.5.0", + "main": "index.html", + "repository": "git@github.com:b-u-i-d-l/unifi.git", + "author": "BUIDL ", + "license": "MIT", + "devDependencies": { + "@openzeppelin/contracts": "^3.1.0", + "@uniswap/v2-core": "^1.0.1", + "@uniswap/v2-periphery": "^1.1.0-beta.0", + "prettier": "^2.1.0", + "prettier-plugin-solidity": "^1.0.0-alpha.56", + "solc": "^0.7.0", + "solidity-docgen": "^0.5.4" + }, + "scripts": { + "docs": "yarn docs:docgen && yarn docs:mkdocs:serve", + "docs:build": "yarn docs:docgen && yarn docs:mkdocs:build", + "docs:clean": "rm -r docs/{md-build,build}", + "docs:serve": "yarn docs:docgen && yarn docs:mkdocs:serve", + "docs:docgen": "cd docs && py-solidity-docgen --input ../contracts --output md-build && cp ../*.md md-build && ./to_lowercase.sh", + "docs:mkdocs:build": "cd docs && mkdocs build", + "docs:mkdocs:serve": "yarn docs:docgen && cd docs && mkdocs serve" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..86ba226 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,815 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@oclif/command@^1.5.20", "@oclif/command@^1.6.1": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.0.tgz#c1a499b10d26e9d1a611190a81005589accbb339" + integrity sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw== + dependencies: + "@oclif/config" "^1.15.1" + "@oclif/errors" "^1.3.3" + "@oclif/parser" "^3.8.3" + "@oclif/plugin-help" "^3" + debug "^4.1.1" + semver "^7.3.2" + +"@oclif/config@^1.15.1": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.17.0.tgz#ba8639118633102a7e481760c50054623d09fcab" + integrity sha512-Lmfuf6ubjQ4ifC/9bz1fSCHc6F6E653oyaRXxg+lgT4+bYf9bk+nqrUpAbrXyABkCqgIBiFr3J4zR/kiFdE1PA== + dependencies: + "@oclif/errors" "^1.3.3" + "@oclif/parser" "^3.8.0" + debug "^4.1.1" + globby "^11.0.1" + is-wsl "^2.1.1" + tslib "^2.0.0" + +"@oclif/errors@^1.2.2", "@oclif/errors@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.3.tgz#fb597dfbc58c6b8609dc0b2fdf91a2d487818a82" + integrity sha512-EJR6AIOEkt/NnARNIVAskPDVtdhtO5TTNXmhDrGqMoWVsr0R6DkkLrMyq95BmHvlVWM1nduoq4fQPuCyuF2jaA== + dependencies: + clean-stack "^3.0.0" + fs-extra "^9.0.1" + indent-string "^4.0.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +"@oclif/linewrap@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" + integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== + +"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.3": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.5.tgz#c5161766a1efca7343e1f25d769efbefe09f639b" + integrity sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg== + dependencies: + "@oclif/errors" "^1.2.2" + "@oclif/linewrap" "^1.0.0" + chalk "^2.4.2" + tslib "^1.9.3" + +"@oclif/plugin-help@^3", "@oclif/plugin-help@^3.0.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.2.0.tgz#b2c1112f49202ebce042f86b2e42e49908172ef1" + integrity sha512-7jxtpwVWAVbp1r46ZnTK/uF+FeZc6y4p1XcGaIUuPAp7wx6NJhIRN/iMT9UfNFX/Cz7mq+OyJz+E+i0zrik86g== + dependencies: + "@oclif/command" "^1.5.20" + "@oclif/config" "^1.15.1" + chalk "^2.4.1" + indent-string "^4.0.0" + lodash.template "^4.4.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + widest-line "^3.1.0" + wrap-ansi "^4.0.0" + +"@openzeppelin/contracts@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.1.0.tgz#bcea457ef89069fbe5a617f50b25b6a8272895d5" + integrity sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ== + +"@solidity-parser/parser@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.7.0.tgz#b8c69c408c729413c090de6bc4f92bb73442ea68" + integrity sha512-YJ333ezgd9slnwCpFQVfsBcYsTcLWZRpVswlKgS82YDZPzzNtVnkEs5DX5+jMsu8PNnVxwZuxC6ucukima9x6w== + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@uniswap/lib@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-1.1.1.tgz#0afd29601846c16e5d082866cbb24a9e0758e6bc" + integrity sha512-2yK7sLpKIT91TiS5sewHtOa7YuM8IuBXVl4GZv2jZFys4D2sY7K5vZh6MqD25TPA95Od+0YzCVq6cTF2IKrOmg== + +"@uniswap/v2-core@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.0.tgz#e0fab91a7d53e8cafb5326ae4ca18351116b0844" + integrity sha512-BJiXrBGnN8mti7saW49MXwxDBRFiWemGetE58q8zgfnPPzQKq55ADltEILqOt6VFZ22kVeVKbF8gVd8aY3l7pA== + +"@uniswap/v2-core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" + integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== + +"@uniswap/v2-periphery@^1.1.0-beta.0": + version "1.1.0-beta.0" + resolved "https://registry.yarnpkg.com/@uniswap/v2-periphery/-/v2-periphery-1.1.0-beta.0.tgz#20a4ccfca22f1a45402303aedb5717b6918ebe6d" + integrity sha512-6dkwAMKza8nzqYiXEr2D86dgW3TTavUvCR0w2Tu33bAbM8Ah43LKAzH7oKKPRT5VJQaMi1jtkGs1E8JPor1n5g== + dependencies: + "@uniswap/lib" "1.1.1" + "@uniswap/v2-core" "1.0.0" + +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@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +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: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +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== + +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== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +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@^3.0.1: + 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" + +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" + +clean-stack@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-3.0.0.tgz#a7c249369fcf0f33c7888c20ea3f3dc79620211f" + integrity sha512-RHxtgFvXsRQ+1AM7dlozLDY7ssmvUUh0XEnfnyhYgJTO6beNZHBogiaCwGM9Q3rFrUkYxOtsZRC0zAturg5bjg== + dependencies: + escape-string-regexp "4.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== + +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== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +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= + +debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +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" + +dir-to-object@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-to-object/-/dir-to-object-2.0.0.tgz#29723e9bd1c3e58e4f307bd04ff634c0370c8f8a" + integrity sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA== + +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== + +emoji-regex@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" + integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== + +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== + +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= + +esprima-extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" + integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw== + dependencies: + esprima "^4.0.0" + +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== + +extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" + integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q== + dependencies: + esprima-extract-comments "^1.1.0" + parse-code-context "^1.0.0" + +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + +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" + +follow-redirects@^1.12.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== + +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@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" + +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= + +glob-parent@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^11.0.0, globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +handlebars@^4.7.6: + version "4.7.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" + integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== + 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" + +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= + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +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: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-docker@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== + +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-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-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +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-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" + +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== + +json5@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +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@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +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" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.template@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash@^4.17.15: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +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= + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +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.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "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= + +parse-code-context@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" + integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== + +path-is-absolute@^1.0.0: + 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-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== + +picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +prettier-plugin-solidity@^1.0.0-alpha.56: + version "1.0.0-alpha.56" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.56.tgz#9130b18eacecbdff401acb0820f39e95b12a5c02" + integrity sha512-+RtJCTQEgHSfOZ3ehHeIElvzVjnYz1qy/mzgiNL4MobInUgXS+hi1iVNiU21KcSVR8Z75DApfofzEt0heddsmg== + dependencies: + "@solidity-parser/parser" "^0.7.0" + dir-to-object "^2.0.0" + emoji-regex "^9.0.0" + escape-string-regexp "^4.0.0" + extract-comments "^1.1.0" + prettier "^2.0.5" + semver "^7.3.2" + string-width "^4.2.0" + +prettier@^2.0.5, prettier@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.0.tgz#5a9789f767a243118c60f3e56d95cb6544914fbb" + integrity sha512-lz28cCbA1cDFHVuY8vvj6QuqOwIpyIfPUYkSl8AZ/vxH8qBXMMjE2knfLHCrZCmUsK/H1bg1P0tOo0dJkTJHvw== + +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== + +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== + +rimraf@^2.2.8: + 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" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +solc@^0.6.7: + 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" + +solc@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.0.tgz#f242ba1888a0b7fe3070a82cd9fd09fcea3e15ad" + integrity sha512-4mpz0XimxHpR7X/YIpM2C4hX+wGTenACJX8Vch6I1jgwwQoZElqnaKHD/f2z9/B8jdU5eim5NGcgg3XEY5rcrA== + 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" + +solidity-docgen@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.5.4.tgz#933d043368d34079a326cb7225bbf043ab887e45" + integrity sha512-ecOMN+T4j/Db3WEOkr/HJ7eS2WOn56JvpwwyTPQe5PhnPx+WJ0iLtS5e/ChiThVxvDDq0fQptniP09MrjjQ4Gg== + dependencies: + "@oclif/command" "^1.6.1" + "@oclif/config" "^1.15.1" + "@oclif/errors" "^1.2.2" + "@oclif/plugin-help" "^3.0.0" + globby "^11.0.0" + handlebars "^4.7.6" + json5 "^2.1.3" + lodash "^4.17.15" + micromatch "^4.0.2" + minimatch "^3.0.4" + semver "^7.3.2" + solc "^0.6.7" + +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== + +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@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.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@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.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" + +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" + +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" + +tslib@^1.9.3: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tslib@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + +uglify-js@^3.1.4: + version "3.10.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.2.tgz#8cfa1209fd04199cc8a7f9930ddedb30b0f1912d" + integrity sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow== + +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrap-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131" + integrity sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg== + dependencies: + ansi-styles "^3.2.0" + string-width "^2.1.1" + strip-ansi "^4.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=