From f85ce3fc316e488e512374c7325f85a083d1113a Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Mon, 24 Aug 2020 23:59:07 +0200 Subject: [PATCH 01/19] Add docs --- .gitignore | 270 +++++++++++++++++- .prettierrc | 15 + ...VotingTokensForStableCoinFunctionality.sol | 83 ++++-- contracts/stableCoin/standalone/Address.sol | 41 ++- contracts/stableCoin/standalone/Context.sol | 8 +- contracts/stableCoin/standalone/ERC20.sol | 15 +- contracts/stableCoin/standalone/IERC20.sol | 8 +- .../stableCoin/standalone/IStableCoin.sol | 123 ++++++-- contracts/stableCoin/standalone/SafeMath.sol | 20 +- .../stableCoin/standalone/StableCoin.sol | 11 +- docs/Makefile | 20 ++ docs/docs.json | 132 +++++++++ docs/make.bat | 35 +++ docs/requirements.in | 3 + docs/requirements.txt | 37 +++ docs/source/api.rst | 16 ++ docs/source/conf.py | 90 ++++++ docs/source/index.rst | 21 ++ 18 files changed, 867 insertions(+), 81 deletions(-) create mode 100644 .prettierrc create mode 100644 docs/Makefile create mode 100644 docs/docs.json create mode 100644 docs/make.bat create mode 100644 docs/requirements.in create mode 100644 docs/requirements.txt create mode 100644 docs/source/api.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst diff --git a/.gitignore b/.gitignore index d5b1a3e..0177b03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,268 @@ -/**/.DS_Store /**/.vscode /**/spa/**/style.css -/**/node_modules -/**/package-lock.json -/**/npm/dist \ No newline at end of file + +docs/build + +# 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/.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/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index ae5ddb9..ab5c65f 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -3,23 +3,37 @@ pragma solidity 0.7.0; contract MintNewVotingTokensForStableCoinFunctionality { - function onStart(address, address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); address stablecoinauthorized = 0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A; - 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()); address stablecoinauthorized = 0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A; - 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)); @@ -29,32 +43,36 @@ 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++) { + 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); @@ -62,24 +80,41 @@ contract MintNewVotingTokensForStableCoinFunctionality { } 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/Address.sol b/contracts/stableCoin/standalone/Address.sol index 774e56c..4af9fb8 100644 --- a/contracts/stableCoin/standalone/Address.sol +++ b/contracts/stableCoin/standalone/Address.sol @@ -30,7 +30,9 @@ library Address { uint256 size; // solhint-disable-next-line no-inline-assembly - assembly { size := extcodesize(account) } + assembly { + size := extcodesize(account) + } return size > 0; } @@ -54,7 +56,7 @@ library Address { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (bool success, ) = recipient.call{ value: amount }(""); + (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } @@ -77,7 +79,7 @@ library Address { * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); + return functionCall(target, data, "Address: low-level call failed"); } /** @@ -86,7 +88,11 @@ library Address { * * _Available since v3.1._ */ - function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } @@ -101,8 +107,13 @@ library Address { * * _Available since v3.1._ */ - function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return + functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** @@ -111,16 +122,26 @@ library Address { * * _Available since v3.1._ */ - function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } - function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { + function _functionCallWithValue( + address target, + bytes memory data, + uint256 weiValue, + string memory errorMessage + ) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); + (bool success, bytes memory returndata) = target.call{value: weiValue}(data); if (success) { return returndata; } else { @@ -138,4 +159,4 @@ library Address { } } } -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/Context.sol b/contracts/stableCoin/standalone/Context.sol index df4d6e1..a193e82 100644 --- a/contracts/stableCoin/standalone/Context.sol +++ b/contracts/stableCoin/standalone/Context.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; -/* +/** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct @@ -13,12 +13,12 @@ pragma solidity ^0.7.0; * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { - function _msgSender() internal view virtual returns (address payable) { + function _msgSender() internal virtual view returns (address payable) { return msg.sender; } - function _msgData() internal view virtual returns (bytes memory) { + function _msgData() internal virtual view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol index 6d9fa02..883bd0e 100644 --- a/contracts/stableCoin/standalone/ERC20.sol +++ b/contracts/stableCoin/standalone/ERC20.sol @@ -55,15 +55,15 @@ abstract contract ERC20 is Context, IERC20 { * All three of these values are immutable: they can only be set once during * construction. */ - function init(string memory name, string memory symbol) internal { + function init(string memory name, string memory symbol) internal { require( keccak256(bytes(_symbol)) == keccak256(""), "Init already Called!" ); - _name = name; - _symbol = symbol; - _decimals = 18; - } + _name = name; + _symbol = symbol; + _decimals = 18; + } /** * @dev Returns the name of the token. @@ -275,7 +275,8 @@ abstract contract ERC20 is Context, IERC20 { emit Transfer(sender, recipient, amount); } - /** @dev Creates `amount` tokens and assigns them to `account`, increasing + /** + * @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. @@ -373,4 +374,4 @@ abstract contract ERC20 is Context, IERC20 { address to, uint256 amount ) internal virtual {} -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/IERC20.sol b/contracts/stableCoin/standalone/IERC20.sol index c6eb6d3..841d27a 100644 --- a/contracts/stableCoin/standalone/IERC20.sol +++ b/contracts/stableCoin/standalone/IERC20.sol @@ -59,7 +59,11 @@ interface IERC20 { * * Emits a {Transfer} event. */ - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to @@ -74,4 +78,4 @@ interface IERC20 { * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 7d4039b..77432be 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -2,7 +2,22 @@ pragma solidity ^0.7.0; +/** + * @title Interface for the "uSD" AKA "uniswap State Dollar", Unifi stablecoin. + * @dev Define the interface for the usD + */ interface IStableCoin { + /** + * 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 list 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,35 +28,76 @@ interface IStableCoin { uint256[] calldata mintables ) external; - function tierData() external view returns(uint256[] memory, uint256[] memory); + // |--------------------------------------------------------------------------------| + // | ----- GETTTERS ----- + // |--------------------------------------------------------------------------------| - function availableToMint() external view returns(uint256); + /** + * @return All tiers of data of the carried context + */ + function tierData() external view returns (uint256[] memory, uint256[] memory); - function doubleProxy() external view returns (address); + /** + * @return The amount of available mintable token + */ + function availableToMint() external view returns (uint256); - function setDoubleProxy(address newDoubleProxy) external; + /** + * @return The address for the doubleProxy smart contract + */ + function doubleProxy() external view returns (address); + /** + * @return List of allowed Uniswap pairs + */ function allowedPairs() external view returns (address[] memory); - function setAllowedPairs(address[] calldata newAllowedPairs) external; + // DOCUMENT + function differences() external view returns (uint256, uint256); - function rebalanceRewardMultiplier() - external - view - returns (uint256[] memory); + /** + * @return The multiplier used to compute the rebalancing rewards + */ + function rebalanceRewardMultiplier() external view returns (uint256[] memory); - function differences() external view returns (uint256, uint256); + // |--------------------------------------------------------------------------------| + // | ----- SETTTERS ----- + // |--------------------------------------------------------------------------------| - function calculateRebalanceByDebtReward(uint256 burnt) - external - view - returns (uint256); + /** + * @param newDoubleProxy new DoubleProxy to set + */ + function setDoubleProxy(address newDoubleProxy) external; + + /** + * @param newAllowedPairs list of Uniswap pairs to be whitelisted + */ + function setAllowedPairs(address[] calldata newAllowedPairs) external; + // |--------------------------------------------------------------------------------| + // | ----- CORE FUNCTIONS ----- + // |--------------------------------------------------------------------------------| + + /** + * @dev + * @param burnt amount of of uSD burnt + */ + function calculateRebalanceByDebtReward(uint256 burnt) external view returns (uint256); + + /** + * @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); + /** + * @dev + */ function mint( uint256 pairIndex, uint256 amount0, @@ -50,6 +106,9 @@ interface IStableCoin { uint256 amount1Min ) external returns (uint256); + /** + * @dev + */ function burn( uint256 pairIndex, uint256 pairAmount, @@ -57,6 +116,9 @@ interface IStableCoin { uint256 amount1 ) external returns (uint256, uint256); + /** + * @dev + */ function rebalanceByCredit( uint256 pairIndex, uint256 pairAmount, @@ -64,20 +126,24 @@ interface IStableCoin { uint256 amount1 ) external returns (uint256); - function rebalanceByDebt(uint256 amount) external returns(uint256); + /** + * @dev + */ + function rebalanceByDebt(uint256 amount) external returns (uint256); } +// -------------------------------------------------------------------------------------- + interface IDoubleProxy { function proxy() external view returns (address); } +// -------------------------------------------------------------------------------------- + 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); @@ -89,18 +155,22 @@ interface IMVDProxy { returns (bytes memory returnData); } +// -------------------------------------------------------------------------------------- + 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 { function getAmountsOut(uint256 amountIn, address[] calldata path) external @@ -135,6 +205,11 @@ interface IUniswapV2Router { ); } +// -------------------------------------------------------------------------------------- + +/** + * @title Interface + */ interface IUniswapV2Pair { function decimals() external pure returns (uint8); @@ -154,4 +229,4 @@ interface IUniswapV2Pair { uint112 reserve1, uint32 blockTimestampLast ); -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/SafeMath.sol b/contracts/stableCoin/standalone/SafeMath.sol index 4f9c084..541864b 100644 --- a/contracts/stableCoin/standalone/SafeMath.sol +++ b/contracts/stableCoin/standalone/SafeMath.sol @@ -57,7 +57,11 @@ library SafeMath { * * - Subtraction cannot overflow. */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + function sub( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; @@ -116,7 +120,11 @@ library SafeMath { * * - The divisor cannot be zero. */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + function div( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold @@ -152,8 +160,12 @@ library SafeMath { * * - The divisor cannot be zero. */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + function mod( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } -} \ No newline at end of file +} diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 3098384..ae88fdd 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -21,6 +21,9 @@ contract StableCoin is ERC20, IStableCoin { uint256 private _lastRedeemBlock; + /** + Stablecoin constructor function. + */ constructor( string memory name, string memory symbol, @@ -44,6 +47,10 @@ contract StableCoin is ERC20, IStableCoin { ); } + /** + * Initialize the StableCoin. + * @inheritdoc IStableCoin + */ function init( string memory name, string memory symbol, @@ -253,7 +260,7 @@ contract StableCoin is ERC20, IStableCoin { ) public override _forAllowedPair(pairIndex) returns (uint256 redeemed) { require( block.number >= - _lastRedeemBlock + + _lastRedeemBlock + IStateHolder( IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) .getStateHolderAddress() @@ -450,4 +457,4 @@ contract StableCoin is ERC20, IStableCoin { } return string(bStr); } -} \ No newline at end of file +} diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/docs.json b/docs/docs.json new file mode 100644 index 0000000..b63e6ac --- /dev/null +++ b/docs/docs.json @@ -0,0 +1,132 @@ + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IDoubleProxy ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IMVDFunctionalitiesManager ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IMVDProxy ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IStableCoin ======= +Developer Documentation +{ + "details": "Define the interface for the usD", + "kind": "dev", + "methods": + { + "allowedPairs()": + { + "details": "Get the list of allowed Uniswap pairs", + "returns": + { + "_0": "List of allowed Uniswap pairs" + } + }, + "availableToMint()": + { + "details": "Get the amount of available mintable token" + }, + "calculateRebalanceByDebtReward(uint256)": + { + "details": "@param burnt amount of of uSD burnt" + }, + "differences()": + { + "details": "GET" + }, + "doubleProxy()": + { + "details": "Get the address for the doubleProxy smart contract" + }, + "fromTokenToStable(address,uint256)": + { + "details": "Convert from one of the pooled token to uSD", + "params": + { + "amount": "Of token to be converted", + "tokenAddress": "Address of the token to convert" + }, + "returns": + { + "_0": "Amount of uSD tokens" + } + }, + "init(string,string,address,address[],uint256[],uint256[],uint256[])": + { + "details": "Constructor signature", + "params": + { + "allowedPairs": "list of Uniswap Pairs to be set as whitelisted source tokens", + "doubleProxy": "address for the DoubleProxy", + "mintables": "max amount of mintables inside a timeWindow", + "name": "name of the StableCoin ERC20 token", + "rebalanceRewardMultiplier": "multiplier used to compute how many unifi tokens to mint during uSD rebalance", + "symbol": "ticker for the StableCoin ERC20 token", + "timeWindows": "time windows inside which some time-delimited operations can be performed" + } + }, + "setAllowedPairs(address[])": + { + "details": "Set the whitelisted Uniswap pairs", + "params": + { + "newAllowedPairs": "list of Uniswap pairs to be whitelisted" + } + }, + "setDoubleProxy(address)": + { + "details": "Set a new DoubleProxy", + "params": + { + "newDoubleProxy": "new DoubleProxy to set" + } + }, + "tierData()": + { + "details": "Get all tiers of data of the carried context" + } + }, + "title": "Interface for the \"uSD\" AKA \"uniswap State Dollar\", Unifi stablecoin.", + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IStateHolder ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IUniswapV2Pair ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "title": "Interface", + "version": 1 +} + +======= ../contracts/stableCoin/standalone/IStableCoin.sol:IUniswapV2Router ======= +Developer Documentation +{ + "kind": "dev", + "methods": {}, + "version": 1 +} diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..6247f7e --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 0000000..08cf9e8 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1,3 @@ +sphinx +sphinxcontrib-soliditydomain +sphinx-rtd-theme diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..d80e570 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,37 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +alabaster==0.7.12 # via sphinx +antlr4-python3-runtime==4.7.1 # via sphinxcontrib-soliditydomain +babel==2.8.0 # via sphinx +certifi==2020.6.20 # via requests +chardet==3.0.4 # via requests +docutils==0.16 # via sphinx +idna==2.10 # via requests +imagesize==1.2.0 # via sphinx +jinja2==2.11.2 # via sphinx +markupsafe==1.1.1 # via jinja2 +packaging==20.4 # via sphinx +peewee==3.13.3 # via sphinxcontrib-soliditydomain +pygments==2.6.1 # via sphinx +pyparsing==2.4.7 # via packaging +pytz==2020.1 # via babel +requests==2.24.0 # via sphinx +six==1.15.0 # via packaging +snowballstemmer==2.0.0 # via sphinx +sphinx-rtd-theme==0.5.0 # via -r requirements.in +sphinx==3.1.2 # via -r requirements.in, sphinx-rtd-theme +sphinxcontrib-applehelp==1.0.2 # via sphinx +sphinxcontrib-devhelp==1.0.2 # via sphinx +sphinxcontrib-htmlhelp==1.0.3 # via sphinx +sphinxcontrib-jsmath==1.0.1 # via sphinx +sphinxcontrib-qthelp==1.0.3 # via sphinx +sphinxcontrib-serializinghtml==1.1.4 # via sphinx +sphinxcontrib-soliditydomain==0.5.1 # via -r requirements.in +urllib3==1.25.10 # via requests + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..90b33a5 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,16 @@ +############# +API Reference +############# + + +.. autosolinterface:: IStableCoin + :members: + +.. autosolinterface:: IDoubleProxy + :members: + +.. autosolinterface:: IUniswapV2Router + :members: + +.. autosolinterface:: IUniswapV2Pair + :members: diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..c52ed61 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,90 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# + +import os +import sys + +sys.path.insert(0, os.path.abspath(".")) + + +# -- Project information ----------------------------------------------------- + +project = "unifi" +copyright = "2020, unifi" +author = "unifi" + + +# The short X.Y version +version = "0.5.0" +# The full version, including alpha/beta/rc tags +release = "0.5.0" + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinxcontrib.soliditydomain", + "sphinx.ext.intersphinx", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# -- Options for HTML output ------------------------------------------------- + +# Logo +html_logo = "" + + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + "display_version": True, + "sticky_navigation": True, + "collapse_navigation": False, + "navigation_depth": 4, + "logo_only": True, +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +html_css_files = ["css/custom.css"] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..e37646e --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,21 @@ +.. unifi documentation master file, created by + sphinx-quickstart on Thu Aug 6 20:57:06 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to unifi's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents:' + + api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` From 0711253a605b06e06cbe50c41432a8275a985c0a Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 25 Aug 2020 18:13:31 +0200 Subject: [PATCH 02/19] WIP --- ...VotingTokensForStableCoinFunctionality.sol | 3 + .../stableCoin/standalone/IStableCoin.sol | 33 +++-- .../stableCoin/standalone/StableCoin.sol | 114 ++++++++++++++++-- 3 files changed, 132 insertions(+), 18 deletions(-) diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index ab5c65f..8c3853b 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -2,6 +2,9 @@ pragma solidity 0.7.0; +/** + * @title Mint Voting Tokens (unifi) by burning Stable Coin (uSD) // DOCUMENT + */ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 77432be..5bdf3d6 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -13,7 +13,7 @@ interface IStableCoin { * @param name name of the StableCoin ERC20 token * @param symbol ticker for the StableCoin ERC20 token * @param doubleProxy address for the DoubleProxy - * @param allowedPairs list of Uniswap Pairs to be set as whitelisted source tokens + * @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 @@ -48,7 +48,7 @@ interface IStableCoin { function doubleProxy() external view returns (address); /** - * @return List of allowed Uniswap pairs + * @return Array of allowed Uniswap pairs */ function allowedPairs() external view returns (address[] memory); @@ -79,7 +79,7 @@ interface IStableCoin { // |--------------------------------------------------------------------------------| /** - * @dev + * @dev // DOCUMENT * @param burnt amount of of uSD burnt */ function calculateRebalanceByDebtReward(uint256 burnt) external view returns (uint256); @@ -96,7 +96,14 @@ interface IStableCoin { returns (uint256); /** - * @dev + * Mint logic of the StableCoin. + * @dev Mint the uSD token + * @param pairIndex + * @param amount0 + * @param amount1 + * @param amount0min + * @param amount1min + * @return Amount of freshly minted uSD token */ function mint( uint256 pairIndex, @@ -107,7 +114,7 @@ interface IStableCoin { ) external returns (uint256); /** - * @dev + * @dev // DOCUMENT */ function burn( uint256 pairIndex, @@ -117,7 +124,7 @@ interface IStableCoin { ) external returns (uint256, uint256); /** - * @dev + * @dev // DOCUMENT */ function rebalanceByCredit( uint256 pairIndex, @@ -127,19 +134,21 @@ interface IStableCoin { ) external returns (uint256); /** - * @dev + * @dev // DOCUMENT */ function rebalanceByDebt(uint256 amount) external returns (uint256); } // -------------------------------------------------------------------------------------- +// DOCUMENT interface IDoubleProxy { function proxy() external view returns (address); } // -------------------------------------------------------------------------------------- +// DOCUMENT interface IMVDProxy { function getToken() external view returns (address); @@ -157,12 +166,14 @@ interface IMVDProxy { // -------------------------------------------------------------------------------------- +// DOCUMENT interface IMVDFunctionalitiesManager { function isAuthorizedFunctionality(address functionality) external view returns (bool); } // -------------------------------------------------------------------------------------- +// DOCUMENT interface IStateHolder { function getBool(string calldata varName) external view returns (bool); @@ -171,6 +182,7 @@ interface IStateHolder { // -------------------------------------------------------------------------------------- +// DOCUMENT interface IUniswapV2Router { function getAmountsOut(uint256 amountIn, address[] calldata path) external @@ -207,20 +219,27 @@ interface IUniswapV2Router { // -------------------------------------------------------------------------------------- +// DOCUMENT /** * @title Interface */ interface IUniswapV2Pair { + // DOCUMENT function decimals() external pure returns (uint8); + // DOCUMENT function totalSupply() external view returns (uint256); + // DOCUMENT function token0() external view returns (address); + // DOCUMENT function token1() external view returns (address); + // DOCUMENT function balanceOf(address account) external view returns (uint256); + // DOCUMENT function getReserves() external view diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index ae88fdd..a1f945a 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 Cotntract for the "uSD" Stable Coin. It's an ERC20 token extended with the IStableCoin + * interface. + */ contract StableCoin is ERC20, IStableCoin { + // |--------------------------------------------------------------------------------| + // | ----- ATTRIBUTES ----- | + // |--------------------------------------------------------------------------------| address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; @@ -21,8 +30,11 @@ contract StableCoin is ERC20, IStableCoin { uint256 private _lastRedeemBlock; + // |--------------------------------------------------------------------------------| + // | ----- CONSTRUCTOR ----- | + // |--------------------------------------------------------------------------------| /** - Stablecoin constructor function. + * @dev Contract constructor. See StableCoin.init() docs. */ constructor( string memory name, @@ -33,7 +45,7 @@ contract StableCoin is ERC20, IStableCoin { uint256[] memory timeWindows, uint256[] memory mintables ) { - if (doubleProxy == address(0)) { + if (doubleProxy == address(0)) { // DOCUMENT return; } init( @@ -70,6 +82,13 @@ contract StableCoin is ERC20, IStableCoin { _mintables = mintables; } + // |--------------------------------------------------------------------------------| + // | ----- GETTERS ----- | + // |--------------------------------------------------------------------------------| + + /** + * @inheritdoc IStableCoin + */ function tierData() public override @@ -79,6 +98,9 @@ contract StableCoin is ERC20, IStableCoin { return (_timeWindows, _mintables); } + /** + * @inheritdoc IStableCoin + */ function availableToMint() public override view returns (uint256) { uint256 mintable @@ -95,39 +117,61 @@ contract StableCoin is ERC20, IStableCoin { return minted >= mintable ? 0 : mintable - minted; } + /** + * @inheritdoc IStableCoin + */ function doubleProxy() public override view returns (address) { return _doubleProxy; } - function setDoubleProxy(address newDoubleProxy) + /** + * @inheritdoc IStableCoin + */ + function rebalanceRewardMultiplier() public override - _byCommunity + view + returns (uint256[] memory) { - _doubleProxy = newDoubleProxy; + return _rebalanceRewardMultiplier; } + /** + * @inheritdoc IStableCoin + */ function allowedPairs() public override view returns (address[] memory) { return _allowedPairs; } - function setAllowedPairs(address[] memory newAllowedPairs) + // |--------------------------------------------------------------------------------| + // | ----- SETTERS ----- | + // |--------------------------------------------------------------------------------| + + /** + * @inheritdoc IStableCoin + */ + function setDoubleProxy(address newDoubleProxy) public override _byCommunity { - _allowedPairs = newAllowedPairs; + _doubleProxy = newDoubleProxy; } - function rebalanceRewardMultiplier() + /** + * @inheritdoc IStableCoin + */ + function setAllowedPairs(address[] memory newAllowedPairs) public override - view - returns (uint256[] memory) + _byCommunity { - return _rebalanceRewardMultiplier; + _allowedPairs = newAllowedPairs; } + /** + * @inheritdoc IStableCoin + */ function differences() public override @@ -148,6 +192,9 @@ contract StableCoin is ERC20, IStableCoin { : 0; } + /** + * @inheritdoc IStableCoin + */ function calculateRebalanceByDebtReward(uint256 burnt) public override @@ -169,6 +216,9 @@ contract StableCoin is ERC20, IStableCoin { _rebalanceRewardMultiplier[1]; } + /** + * @inheritdoc IStableCoin + */ function fromTokenToStable(address tokenAddress, uint256 amount) public override @@ -184,6 +234,9 @@ contract StableCoin is ERC20, IStableCoin { return result * 10**remainingDecimals; } + /** + * @inheritdoc IStableCoin + */ function mint( uint256 pairIndex, uint256 amount0, @@ -222,6 +275,9 @@ contract StableCoin is ERC20, IStableCoin { _mint(msg.sender, minted); } + /** + * @inheritdoc IStableCoin + */ function burn( uint256 pairIndex, uint256 pairAmount, @@ -252,6 +308,9 @@ contract StableCoin is ERC20, IStableCoin { ); } + /** + * @inheritdoc IStableCoin + */ function rebalanceByCredit( uint256 pairIndex, uint256 pairAmount, @@ -290,6 +349,9 @@ contract StableCoin is ERC20, IStableCoin { require(redeemed <= credit, "Cannot redeem given pair amount"); } + /** + * @inheritdoc IStableCoin + */ function rebalanceByDebt(uint256 amount) public override returns(uint256 reward) { require(amount > 0, "You must insert a positive value"); (, uint256 debt) = differences(); @@ -306,6 +368,9 @@ contract StableCoin is ERC20, IStableCoin { ); } + /** + * // DOCUMENT + */ modifier _byCommunity() { require( IMVDFunctionalitiesManager( @@ -318,6 +383,9 @@ contract StableCoin is ERC20, IStableCoin { _; } + /** + * // DOCUMENT + */ modifier _forAllowedPair(uint256 pairIndex) { require( pairIndex >= 0 && pairIndex < _allowedPairs.length, @@ -326,6 +394,9 @@ contract StableCoin is ERC20, IStableCoin { _; } + /** + * // DOCUMENT + */ function _getPairData(uint256 pairIndex) private view @@ -342,6 +413,9 @@ contract StableCoin is ERC20, IStableCoin { token1 = pair.token1(); } + /** + * // DOCUMENT + */ function _transferTokensAndCheckAllowance( address tokenAddress, uint256 value @@ -350,6 +424,9 @@ contract StableCoin is ERC20, IStableCoin { _checkAllowance(tokenAddress, value); } + /** + * // DOCUMENT + */ function _checkAllowance(address tokenAddress, uint256 value) private { IERC20 token = IERC20(tokenAddress); if (token.allowance(address(this), UNISWAP_V2_ROUTER) <= value) { @@ -360,6 +437,9 @@ contract StableCoin is ERC20, IStableCoin { } } + /** + * // DOCUMENT + */ function _createPoolToken( address firstToken, address secondToken, @@ -402,6 +482,9 @@ contract StableCoin is ERC20, IStableCoin { } } + /** + * // DOCUMENT + */ function _getPairAmount(uint256 i) private view @@ -422,6 +505,9 @@ contract StableCoin is ERC20, IStableCoin { ); } + /** + * // DOCUMENT + */ function _toStateHolderKey(string memory a, string memory b) private pure @@ -430,6 +516,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"; @@ -444,6 +533,9 @@ contract StableCoin is ERC20, IStableCoin { return string(str); } + /** + * // DOCUMENT + */ function _toLowerCase(string memory str) private pure From cbed7a02906140b764acd17438b34ea59953c6fc Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 25 Aug 2020 21:07:19 +0200 Subject: [PATCH 03/19] WIP 2 --- ...VotingTokensForStableCoinFunctionality.sol | 9 + contracts/stableCoin/standalone/ERC20.sol | 41 +--- .../stableCoin/standalone/IStableCoin.sol | 89 ++++++-- .../stableCoin/standalone/StableCoin.sol | 204 +++++------------- package.json | 12 ++ yarn.lock | 103 +++++++++ 6 files changed, 262 insertions(+), 196 deletions(-) create mode 100644 package.json create mode 100644 yarn.lock diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index 8c3853b..7401275 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -31,6 +31,7 @@ contract MintNewVotingTokensForStableCoinFunctionality { ) public { IMVDProxy proxy = IMVDProxy(msg.sender); + // NOTE: Use DFO Protocol to check for authorization require( IStateHolder(proxy.getStateHolderAddress()).getBool( _toStateHolderKey("stablecoin.authorized", _toString(sender)) @@ -82,6 +83,8 @@ contract MintNewVotingTokensForStableCoinFunctionality { } } +// -------------------------------------------------------------------------------------- + interface IMVDProxy { function getToken() external view returns (address); @@ -102,10 +105,14 @@ interface IMVDProxy { ) external; } +// -------------------------------------------------------------------------------------- + interface IMVDFunctionalitiesManager { function isAuthorizedFunctionality(address functionality) external view returns (bool); } +// -------------------------------------------------------------------------------------- + interface IStateHolder { function clear(string calldata varName) external @@ -116,6 +123,8 @@ interface IStateHolder { function getBool(string calldata varName) external view returns (bool); } +// -------------------------------------------------------------------------------------- + interface IERC20 { function mint(uint256 amount) external; diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol index 883bd0e..cddefcf 100644 --- a/contracts/stableCoin/standalone/ERC20.sol +++ b/contracts/stableCoin/standalone/ERC20.sol @@ -56,10 +56,7 @@ abstract contract ERC20 is Context, IERC20 { * construction. */ function init(string memory name, string memory symbol) internal { - require( - keccak256(bytes(_symbol)) == keccak256(""), - "Init already Called!" - ); + require(keccak256(bytes(_symbol)) == keccak256(""), "Init already Called!"); _name = name; _symbol = symbol; _decimals = 18; @@ -119,12 +116,7 @@ abstract contract ERC20 is Context, IERC20 { * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ - function transfer(address recipient, uint256 amount) - public - virtual - override - returns (bool) - { + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } @@ -149,12 +141,7 @@ abstract contract ERC20 is Context, IERC20 { * * - `spender` cannot be the zero address. */ - function approve(address spender, uint256 amount) - public - virtual - override - returns (bool) - { + function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } @@ -200,16 +187,8 @@ abstract contract ERC20 is Context, IERC20 { * * - `spender` cannot be the zero address. */ - function increaseAllowance(address spender, uint256 addedValue) - public - virtual - returns (bool) - { - _approve( - _msgSender(), - spender, - _allowances[_msgSender()][spender].add(addedValue) - ); + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } @@ -267,10 +246,7 @@ abstract contract ERC20 is Context, IERC20 { _beforeTokenTransfer(sender, recipient, amount); - _balances[sender] = _balances[sender].sub( - amount, - "ERC20: transfer amount exceeds balance" - ); + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } @@ -311,10 +287,7 @@ abstract contract ERC20 is Context, IERC20 { _beforeTokenTransfer(account, address(0), amount); - _balances[account] = _balances[account].sub( - amount, - "ERC20: burn amount exceeds balance" - ); + _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 5bdf3d6..0cf63e4 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -28,9 +28,9 @@ interface IStableCoin { uint256[] calldata mintables ) external; - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- GETTTERS ----- - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| /** * @return All tiers of data of the carried context @@ -60,9 +60,9 @@ interface IStableCoin { */ function rebalanceRewardMultiplier() external view returns (uint256[] memory); - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- SETTTERS ----- - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| /** * @param newDoubleProxy new DoubleProxy to set @@ -74,9 +74,9 @@ interface IStableCoin { */ function setAllowedPairs(address[] calldata newAllowedPairs) external; - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- CORE FUNCTIONS ----- - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| /** * @dev // DOCUMENT @@ -139,14 +139,14 @@ interface IStableCoin { function rebalanceByDebt(uint256 amount) external returns (uint256); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| // DOCUMENT interface IDoubleProxy { function proxy() external view returns (address); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| // DOCUMENT interface IMVDProxy { @@ -164,14 +164,14 @@ interface IMVDProxy { returns (bytes memory returnData); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| // DOCUMENT interface IMVDFunctionalitiesManager { function isAuthorizedFunctionality(address functionality) external view returns (bool); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| // DOCUMENT interface IStateHolder { @@ -180,15 +180,46 @@ interface IStateHolder { function getUint256(string calldata varName) external view returns (uint256); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| -// DOCUMENT +/** + * @title Uniswap V2 Router + * @dev Route liquidity back and forth an Uniswap Liquidity Pool. + * For more information see: https://uniswap.org/docs/v2/smart-contracts/router02/ + * + */ interface IUniswapV2Router { + /** + * https://uniswap.org/docs/v2/smart-contracts/library#getamountsout + * Given an input asset amount and an array of token addresses, calculates all subsequent maximum + * output token amounts by calling getReserves for each pair of token addresses in the path in + * turn, and using these to call getAmountOut. Useful for calculating optimal token amounts + * before calling swap. + */ function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); + /** + * @dev Removes liquidity from an ERC-20⇄ERC-20 pool + * + * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity + * + * ===== + * + * @param tokenA A pool token + * @param tokenB A pool token + * @param liquidity The amount of liquidity tokens to remove + * @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 to Recipient of the underlying assets + * @param deadline Unix timestamp after which the transaction will revert + * @returns { + * "amountA": The amount of tokenA received + * "amountB": The amount of tokenB received + * } + */ function removeLiquidity( address tokenA, address tokenB, @@ -199,6 +230,36 @@ interface IUniswapV2Router { uint256 deadline ) external returns (uint256 amountA, uint256 amountB); + /** + * @dev Add Liquidity to an ERC-20⇄ERC-20 pool + * + * - To cover all possible scenarios, msg.sender should have already given the router an allowance + * of at least amountADesired/amountBDesired on tokenA/tokenB. + * - Always adds assets at the ideal ratio, according to the price when the transaction is executed. + * - If a pool for the passed tokens does not exists, one is created automatically, and exactly + * amountADesired/amountBDesired tokens are added. + * + * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity + * + * ===== + * + * @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. + * @param to Recipient of the underlying assets + * @param deadline Unix timestamp after which the transaction will revert + * @returns { + * "amountA": The amount of tokenA sent to the pool + * "amountB": The amount of tokenB sent to the pool + * "liquidity": The amount of liquidity tokens minted. + * } + */ function addLiquidity( address tokenA, address tokenB, @@ -217,11 +278,11 @@ interface IUniswapV2Router { ); } -// -------------------------------------------------------------------------------------- +// -----------------------------------------------------------------------------------------------| // DOCUMENT /** - * @title Interface + * @title Uniswap V2 Pair */ interface IUniswapV2Pair { // DOCUMENT diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index a1f945a..f3378de 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -5,18 +5,17 @@ pragma solidity ^0.7.0; import "./ERC20.sol"; import "./IStableCoin.sol"; - /** * @title StableCoin * @dev Cotntract for the "uSD" Stable Coin. It's an ERC20 token extended with the IStableCoin * interface. */ contract StableCoin is ERC20, IStableCoin { - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- ATTRIBUTES ----- | - // |--------------------------------------------------------------------------------| - address - private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; + // |------------------------------------------------------------------------------------------| + + address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; address private _doubleProxy; @@ -30,9 +29,10 @@ contract StableCoin is ERC20, IStableCoin { uint256 private _lastRedeemBlock; - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- CONSTRUCTOR ----- | - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| + /** * @dev Contract constructor. See StableCoin.init() docs. */ @@ -45,7 +45,8 @@ contract StableCoin is ERC20, IStableCoin { uint256[] memory timeWindows, uint256[] memory mintables ) { - if (doubleProxy == address(0)) { // DOCUMENT + // DOCUMENT + if (doubleProxy == address(0)) { return; } init( @@ -82,19 +83,14 @@ contract StableCoin is ERC20, IStableCoin { _mintables = mintables; } - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- GETTERS ----- | - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| /** * @inheritdoc IStableCoin */ - function tierData() - public - override - view - returns (uint256[] memory, uint256[] memory) - { + function tierData() public override view returns (uint256[] memory, uint256[] memory) { return (_timeWindows, _mintables); } @@ -102,10 +98,8 @@ contract StableCoin is ERC20, IStableCoin { * @inheritdoc IStableCoin */ function availableToMint() public override view returns (uint256) { - - uint256 mintable - = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - if(_timeWindows.length > 0 && block.number < _timeWindows[_timeWindows.length - 1]) { + uint256 mintable = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + 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]; @@ -127,12 +121,7 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin */ - function rebalanceRewardMultiplier() - public - override - view - returns (uint256[] memory) - { + function rebalanceRewardMultiplier() public override view returns (uint256[] memory) { return _rebalanceRewardMultiplier; } @@ -143,53 +132,36 @@ contract StableCoin is ERC20, IStableCoin { return _allowedPairs; } - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| // | ----- SETTERS ----- | - // |--------------------------------------------------------------------------------| + // |------------------------------------------------------------------------------------------| /** * @inheritdoc IStableCoin */ - function setDoubleProxy(address newDoubleProxy) - public - override - _byCommunity - { + function setDoubleProxy(address newDoubleProxy) public override _byCommunity { _doubleProxy = newDoubleProxy; } /** * @inheritdoc IStableCoin */ - function setAllowedPairs(address[] memory newAllowedPairs) - public - override - _byCommunity - { + function setAllowedPairs(address[] memory newAllowedPairs) public override _byCommunity { _allowedPairs = newAllowedPairs; } /** * @inheritdoc IStableCoin */ - function differences() - public - override - view - returns (uint256 credit, uint256 debt) - { + 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; + credit = effectiveAmount > totalSupply ? effectiveAmount - totalSupply : 0; + debt = totalSupply > effectiveAmount ? totalSupply - effectiveAmount : 0; } /** @@ -201,19 +173,14 @@ contract StableCoin is ERC20, IStableCoin { 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 = IUniswapV2Router(UNISWAP_V2_ROUTER).getAmountsOut(burnt, path)[1]; + reward = (reward * _rebalanceRewardMultiplier[0]) / _rebalanceRewardMultiplier[1]; } /** @@ -244,17 +211,10 @@ contract StableCoin is ERC20, IStableCoin { uint256 amount0Min, uint256 amount1Min ) public override _forAllowedPair(pairIndex) returns (uint256 minted) { + // NOTE: Use DFO protocol to check for authorization require( - IStateHolder( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) - .getStateHolderAddress() - ) - .getBool( - _toStateHolderKey( - "stablecoin.authorized", - _toString(address(this)) - ) - ), + IStateHolder(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress()) + .getBool(_toStateHolderKey("stablecoin.authorized", _toString(address(this)))), "Unauthorized action!" ); (address token0, address token1, ) = _getPairData(pairIndex); @@ -268,9 +228,7 @@ contract StableCoin is ERC20, IStableCoin { amount0Min, amount1Min ); - minted = - fromTokenToStable(token0, firstAmount) + - fromTokenToStable(token1, secondAmount); + minted = fromTokenToStable(token0, firstAmount) + fromTokenToStable(token1, secondAmount); require(minted <= availableToMint(), "Minting amount is greater than availability"); _mint(msg.sender, minted); } @@ -283,16 +241,10 @@ contract StableCoin is ERC20, IStableCoin { uint256 pairAmount, uint256 amount0, uint256 amount1 - ) - public - override - _forAllowedPair(pairIndex) - returns (uint256 removed0, uint256 removed1) - { + ) public override _forAllowedPair(pairIndex) returns (uint256 removed0, uint256 removed1) { (address token0, address token1, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); - (removed0, removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER) - .removeLiquidity( + (removed0, removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( token0, token1, pairAmount, @@ -303,8 +255,7 @@ contract StableCoin is ERC20, IStableCoin { ); _burn( msg.sender, - fromTokenToStable(token0, removed0) + - fromTokenToStable(token1, removed1) + fromTokenToStable(token0, removed0) + fromTokenToStable(token1, removed1) ); } @@ -317,24 +268,21 @@ contract StableCoin is ERC20, IStableCoin { uint256 amount0, uint256 amount1 ) 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); _checkAllowance(pairAddress, pairAmount); - (uint256 removed0, uint256 removed1) = IUniswapV2Router( - UNISWAP_V2_ROUTER - ) - .removeLiquidity( + (uint256 removed0, uint256 removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( token0, token1, pairAmount, @@ -343,28 +291,21 @@ contract StableCoin is ERC20, IStableCoin { IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDWalletAddress(), block.timestamp + 1000 ); - redeemed = - fromTokenToStable(token0, removed0) + - fromTokenToStable(token1, removed1); + redeemed = fromTokenToStable(token0, removed0) + fromTokenToStable(token1, removed1); require(redeemed <= credit, "Cannot redeem given pair amount"); } /** * @inheritdoc IStableCoin */ - function rebalanceByDebt(uint256 amount) public override returns(uint256 reward) { + 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"); _burn(msg.sender, amount); IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).submit( "mintNewVotingTokensForStableCoin", - abi.encode( - address(0), - 0, - reward = calculateRebalanceByDebtReward(amount), - msg.sender - ) + abi.encode(address(0), 0, reward = calculateRebalanceByDebtReward(amount), msg.sender) ); } @@ -374,8 +315,7 @@ contract StableCoin is ERC20, IStableCoin { modifier _byCommunity() { require( IMVDFunctionalitiesManager( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) - .getMVDFunctionalitiesManagerAddress() + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDFunctionalitiesManagerAddress() ) .isAuthorizedFunctionality(msg.sender), "Unauthorized Action!" @@ -387,10 +327,7 @@ 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!"); _; } @@ -406,9 +343,7 @@ 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(); } @@ -416,10 +351,7 @@ contract StableCoin is ERC20, IStableCoin { /** * // DOCUMENT */ - function _transferTokensAndCheckAllowance( - address tokenAddress, - uint256 value - ) private { + function _transferTokensAndCheckAllowance(address tokenAddress, uint256 value) private { IERC20(tokenAddress).transferFrom(msg.sender, address(this), value); _checkAllowance(tokenAddress, value); } @@ -438,7 +370,8 @@ contract StableCoin is ERC20, IStableCoin { } /** - * // DOCUMENT + * @dev Use the Uniswap Protocol to add liquidity to a pool. + * @inheritdoc IStableCoin */ function _createPoolToken( address firstToken, @@ -455,10 +388,7 @@ contract StableCoin is ERC20, IStableCoin { uint256 poolAmount ) { - (firstAmount, secondAmount, poolAmount) = IUniswapV2Router( - UNISWAP_V2_ROUTER - ) - .addLiquidity( + (firstAmount, secondAmount, poolAmount) = IUniswapV2Router(UNISWAP_V2_ROUTER).addLiquidity( firstToken, secondToken, originalFirstAmount, @@ -469,40 +399,24 @@ contract StableCoin is ERC20, IStableCoin { block.timestamp + 1000 ); if (firstAmount < originalFirstAmount) { - IERC20(firstToken).transfer( - msg.sender, - originalFirstAmount - firstAmount - ); + IERC20(firstToken).transfer(msg.sender, originalFirstAmount - firstAmount); } if (secondAmount < originalSecondAmount) { - IERC20(secondToken).transfer( - msg.sender, - originalSecondAmount - secondAmount - ); + IERC20(secondToken).transfer(msg.sender, originalSecondAmount - secondAmount); } } /** * // DOCUMENT */ - function _getPairAmount(uint256 i) - private - view - returns (uint256 amount0, uint256 amount1) - { + function _getPairAmount(uint256 i) private view returns (uint256 amount0, uint256 amount1) { (address token0, address token1, address pairAddress) = _getPairData(i); IUniswapV2Pair pair = IUniswapV2Pair(pairAddress); 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); } /** @@ -536,16 +450,10 @@ contract StableCoin is ERC20, IStableCoin { /** * // DOCUMENT */ - 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 (uint256 i = 0; i < bStr.length; i++) { - bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A - ? bytes1(uint8(bStr[i]) + 0x20) - : bStr[i]; + bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i]; } return string(bStr); } diff --git a/package.json b/package.json new file mode 100644 index 0000000..c02f463 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "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": { + "prettier": "^2.1.0", + "prettier-plugin-solidity": "^1.0.0-alpha.56" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..a64cf60 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,103 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@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== + +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== + +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: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +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" + +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== + +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== + +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== + +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== + +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@^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" From da7695565fba33bb0b9d439101fc478cb14c59c0 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 25 Aug 2020 21:40:00 +0200 Subject: [PATCH 04/19] WIP 3 --- .../stableCoin/standalone/IStableCoin.sol | 88 +++++++++++++------ .../stableCoin/standalone/StableCoin.sol | 57 ++++++------ 2 files changed, 91 insertions(+), 54 deletions(-) diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 0cf63e4..dd3e355 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -29,7 +29,7 @@ interface IStableCoin { ) external; // |------------------------------------------------------------------------------------------| - // | ----- GETTTERS ----- + // | ----- GETTERS ----- | // |------------------------------------------------------------------------------------------| /** @@ -61,7 +61,7 @@ interface IStableCoin { function rebalanceRewardMultiplier() external view returns (uint256[] memory); // |------------------------------------------------------------------------------------------| - // | ----- SETTTERS ----- + // | ----- SETTERS ----- | // |------------------------------------------------------------------------------------------| /** @@ -75,19 +75,28 @@ interface IStableCoin { function setAllowedPairs(address[] calldata newAllowedPairs) external; // |------------------------------------------------------------------------------------------| - // | ----- CORE FUNCTIONS ----- + // | ----- CORE FUNCTIONS ----- | // |------------------------------------------------------------------------------------------| /** * @dev // DOCUMENT + * + * ===== + * * @param burnt amount of of uSD burnt */ function calculateRebalanceByDebtReward(uint256 burnt) external view returns (uint256); /** * @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) @@ -98,30 +107,51 @@ interface IStableCoin { /** * Mint logic of the StableCoin. * @dev Mint the uSD token - * @param pairIndex - * @param amount0 - * @param amount1 - * @param amount0min - * @param amount1min + * + * ===== + * + * @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 Amount of freshly minted uSD token */ function mint( uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min + uint256 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin ) external returns (uint256); /** - * @dev // DOCUMENT + * Mint logic of the StableCoin. + * @dev Mint the uSD token + * + * ===== + * + * @param pairIndex Index of the pair inside the allowedPairs array + * @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 amountA The amount of tokenA received + * @return amountB 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 amountA, uint256 amountB); /** * @dev // DOCUMENT @@ -211,14 +241,16 @@ interface IUniswapV2Router { * @param tokenA A pool token * @param tokenB A pool token * @param liquidity The amount of liquidity tokens to remove - * @param amountAmin The minimum amount of tokenA that must be received for the transaction not to revert + * @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 to Recipient of the underlying assets * @param deadline Unix timestamp after which the transaction will revert - * @returns { - * "amountA": The amount of tokenA received - * "amountB": The amount of tokenB received - * } + * + * ===== + * + * @return amountA The amount of tokenA received + * @return amountB The amount of tokenB received + * */ function removeLiquidity( address tokenA, @@ -250,15 +282,17 @@ interface IUniswapV2Router { * 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 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. * @param to Recipient of the underlying assets * @param deadline Unix timestamp after which the transaction will revert - * @returns { - * "amountA": The amount of tokenA sent to the pool - * "amountB": The amount of tokenB sent to the pool - * "liquidity": The amount of liquidity tokens minted. - * } + * + * ===== + * + * @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 addLiquidity( address tokenA, diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index f3378de..a500138 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -7,7 +7,7 @@ import "./IStableCoin.sol"; /** * @title StableCoin - * @dev Cotntract for the "uSD" Stable Coin. It's an ERC20 token extended with the IStableCoin + * @dev Contract for the "uSD" Stable Coin. It's an ERC20 token extended with the IStableCoin * interface. */ contract StableCoin is ERC20, IStableCoin { @@ -203,13 +203,17 @@ contract StableCoin is ERC20, IStableCoin { /** * @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( @@ -217,19 +221,19 @@ contract StableCoin is ERC20, IStableCoin { .getBool(_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"); + minted = fromTokenToStable(tokenA, firstAmount) + fromTokenToStable(tokenB, secondAmount); + require(minted <= availableToMint(), "Minting amount is greater than availability!"); _mint(msg.sender, minted); } @@ -239,23 +243,23 @@ contract StableCoin is ERC20, IStableCoin { function burn( uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1 - ) public override _forAllowedPair(pairIndex) returns (uint256 removed0, uint256 removed1) { - (address token0, address token1, address pairAddress) = _getPairData(pairIndex); + uint256 amountAMin, + uint256 amountBMin + ) public override _forAllowedPair(pairIndex) returns (uint256 removedA, uint256 removedB) { + (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); - (removed0, removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( - token0, - token1, + (removedA, removedB) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( + tokenA, + tokenB, pairAmount, - amount0, - amount1, + amountAMin, + amountBMin, msg.sender, block.timestamp + 1000 ); _burn( msg.sender, - fromTokenToStable(token0, removed0) + fromTokenToStable(token1, removed1) + fromTokenToStable(tokenA, removedA) + fromTokenToStable(tokenB, removedB) ); } @@ -371,7 +375,6 @@ contract StableCoin is ERC20, IStableCoin { /** * @dev Use the Uniswap Protocol to add liquidity to a pool. - * @inheritdoc IStableCoin */ function _createPoolToken( address firstToken, From 59c00813156ac3094f18c72a0ad6a7f860d629ab Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Wed, 26 Aug 2020 18:21:48 +0200 Subject: [PATCH 05/19] Add solidity-docgen --- ...VotingTokensForStableCoinFunctionality.sol | 2 +- contracts/stableCoin/standalone/Address.sol | 2 +- contracts/stableCoin/standalone/Context.sol | 2 +- contracts/stableCoin/standalone/ERC20.sol | 2 +- contracts/stableCoin/standalone/IERC20.sol | 2 +- .../stableCoin/standalone/IStableCoin.sol | 52 +- contracts/stableCoin/standalone/SafeMath.sol | 2 +- .../stableCoin/standalone/StableCoin.sol | 131 ++-- package.json | 4 +- yarn.lock | 688 +++++++++++++++++- 10 files changed, 804 insertions(+), 83 deletions(-) diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index 7401275..6e0c552 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.7.0; +pragma solidity ^0.6.0; /** * @title Mint Voting Tokens (unifi) by burning Stable Coin (uSD) // DOCUMENT diff --git a/contracts/stableCoin/standalone/Address.sol b/contracts/stableCoin/standalone/Address.sol index 4af9fb8..6b28275 100644 --- a/contracts/stableCoin/standalone/Address.sol +++ b/contracts/stableCoin/standalone/Address.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; /** * @dev Collection of functions related to the address type diff --git a/contracts/stableCoin/standalone/Context.sol b/contracts/stableCoin/standalone/Context.sol index a193e82..97c73c4 100644 --- a/contracts/stableCoin/standalone/Context.sol +++ b/contracts/stableCoin/standalone/Context.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; /** * @dev Provides information about the current execution context, including the diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol index cddefcf..126be42 100644 --- a/contracts/stableCoin/standalone/ERC20.sol +++ b/contracts/stableCoin/standalone/ERC20.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; import "./Context.sol"; import "./IERC20.sol"; diff --git a/contracts/stableCoin/standalone/IERC20.sol b/contracts/stableCoin/standalone/IERC20.sol index 841d27a..82708eb 100644 --- a/contracts/stableCoin/standalone/IERC20.sol +++ b/contracts/stableCoin/standalone/IERC20.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index dd3e355..a1b352a 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; /** * @title Interface for the "uSD" AKA "uniswap State Dollar", Unifi stablecoin. @@ -33,46 +33,46 @@ interface IStableCoin { // |------------------------------------------------------------------------------------------| /** - * @return All tiers of data of the carried context + * @return Array of allowed Uniswap pairs */ - function tierData() external view returns (uint256[] memory, uint256[] memory); + function allowedPairs() external view returns (address[] memory); /** * @return The amount of available mintable token */ function availableToMint() external view returns (uint256); + // DOCUMENT + function differences() external view returns (uint256, uint256); + /** * @return The address for the doubleProxy smart contract */ function doubleProxy() external view returns (address); /** - * @return Array of allowed Uniswap pairs + * @return The multiplier used to compute the rebalancing rewards */ - function allowedPairs() external view returns (address[] memory); - - // DOCUMENT - function differences() external view returns (uint256, uint256); + function rebalanceRewardMultiplier() external view returns (uint256[] memory); /** - * @return The multiplier used to compute the rebalancing rewards + * @return All tiers of data of the carried context */ - function rebalanceRewardMultiplier() external view returns (uint256[] memory); + function tierData() external view returns (uint256[] memory, uint256[] memory); // |------------------------------------------------------------------------------------------| // | ----- SETTERS ----- | // |------------------------------------------------------------------------------------------| /** - * @param newDoubleProxy new DoubleProxy to set + * @param newAllowedPairs list of Uniswap pairs to be whitelisted */ - function setDoubleProxy(address newDoubleProxy) external; + function setAllowedPairs(address[] calldata newAllowedPairs) external; /** - * @param newAllowedPairs list of Uniswap pairs to be whitelisted + * @param newDoubleProxy new DoubleProxy to set */ - function setAllowedPairs(address[] calldata newAllowedPairs) external; + function setDoubleProxy(address newDoubleProxy) external; // |------------------------------------------------------------------------------------------| // | ----- CORE FUNCTIONS ----- | @@ -112,11 +112,13 @@ interface IStableCoin { * * @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). + * 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. + * 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 * * ===== * @@ -154,14 +156,20 @@ interface IStableCoin { ) external returns (uint256 amountA, uint256 amountB); /** - * @dev // DOCUMENT + * @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); + uint256 amountA, + uint256 amountB + ) external returns (uint256 redeemed); /** * @dev // DOCUMENT diff --git a/contracts/stableCoin/standalone/SafeMath.sol b/contracts/stableCoin/standalone/SafeMath.sol index 541864b..b2e90e8 100644 --- a/contracts/stableCoin/standalone/SafeMath.sol +++ b/contracts/stableCoin/standalone/SafeMath.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index a500138..2d45bf6 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; import "./ERC20.sol"; import "./IStableCoin.sol"; @@ -44,8 +44,7 @@ contract StableCoin is ERC20, IStableCoin { uint256[] memory rebalanceRewardMultiplier, uint256[] memory timeWindows, uint256[] memory mintables - ) { - // DOCUMENT + ) public { if (doubleProxy == address(0)) { return; } @@ -90,8 +89,8 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin */ - function tierData() public override view returns (uint256[] memory, uint256[] memory) { - return (_timeWindows, _mintables); + function allowedPairs() public override view returns (address[] memory) { + return _allowedPairs; } /** @@ -111,6 +110,20 @@ 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 */ @@ -128,21 +141,14 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin */ - function allowedPairs() public override view returns (address[] memory) { - return _allowedPairs; + function tierData() public override view returns (uint256[] memory, uint256[] memory) { + return (_timeWindows, _mintables); } // |------------------------------------------------------------------------------------------| // | ----- SETTERS ----- | // |------------------------------------------------------------------------------------------| - /** - * @inheritdoc IStableCoin - */ - function setDoubleProxy(address newDoubleProxy) public override _byCommunity { - _doubleProxy = newDoubleProxy; - } - /** * @inheritdoc IStableCoin */ @@ -153,17 +159,14 @@ contract StableCoin is ERC20, IStableCoin { /** * @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; + function setDoubleProxy(address newDoubleProxy) public override _byCommunity { + _doubleProxy = newDoubleProxy; } + // |------------------------------------------------------------------------------------------| + // | ----- CORE FUNCTIONS ----- | + // |------------------------------------------------------------------------------------------| + /** * @inheritdoc IStableCoin */ @@ -264,13 +267,16 @@ contract StableCoin is ERC20, IStableCoin { } /** + * @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( @@ -284,18 +290,18 @@ contract StableCoin is ERC20, IStableCoin { ); _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).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); + redeemed = fromTokenToStable(tokenA, removed0) + fromTokenToStable(tokenB, removed1); require(redeemed <= credit, "Cannot redeem given pair amount"); } @@ -313,6 +319,8 @@ contract StableCoin is ERC20, IStableCoin { ); } + // -------------------------------------------------------------------------------------------| + /** * // DOCUMENT */ @@ -335,6 +343,8 @@ contract StableCoin is ERC20, IStableCoin { _; } + // -------------------------------------------------------------------------------------------| + /** * // DOCUMENT */ @@ -374,38 +384,55 @@ contract StableCoin is ERC20, IStableCoin { } /** - * @dev Use the Uniswap Protocol to add liquidity to a pool. + * @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).addLiquidity( - firstToken, - secondToken, - originalFirstAmount, - originalSecondAmount, - firstAmountMin, - secondAmountMin, + (amountA, amountB, liquidity) = IUniswapV2Router(UNISWAP_V2_ROUTER).addLiquidity( + 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); } } diff --git a/package.json b/package.json index c02f463..feeb550 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "license": "MIT", "devDependencies": { "prettier": "^2.1.0", - "prettier-plugin-solidity": "^1.0.0-alpha.56" + "prettier-plugin-solidity": "^1.0.0-alpha.56", + "solc": "^0.7.0", + "solidity-docgen": "^0.5.4" } } diff --git a/yarn.lock b/yarn.lock index a64cf60..4b6a045 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,16 +2,226 @@ # 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" + "@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== + +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" @@ -27,11 +237,16 @@ emoji-regex@^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, 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" @@ -52,16 +267,310 @@ extract-comments@^1.1.0: 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" @@ -81,12 +590,104 @@ prettier@^2.0.5, prettier@^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== -string-width@^4.2.0: +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== @@ -95,9 +696,92 @@ string-width@^4.2.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= From 2d122ed7f59a08e94af2ccb50a13b7604ac2a347 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Wed, 26 Aug 2020 21:59:30 +0200 Subject: [PATCH 06/19] Restructure docs generation around mkdocs --- .gitignore | 1 + CONTRIBUTING.md | 67 +++++++ README.md | 3 + ...VotingTokensForStableCoinFunctionality.sol | 3 +- .../stableCoin/standalone/IDoubleProxy.sol | 6 + .../standalone/IMWDFunctionalitiesManager.sol | 6 + contracts/stableCoin/standalone/IMWDProxy.sol | 17 ++ .../stableCoin/standalone/IStableCoin.sol | 182 +----------------- .../stableCoin/standalone/IStateHolder.sol | 8 + .../stableCoin/standalone/IUniswapV2Pair.sol | 32 +++ .../standalone/IUniswapV2Router.sol | 101 ++++++++++ .../stableCoin/standalone/StableCoin.sol | 10 +- docs/Makefile | 20 -- docs/docs.json | 132 ------------- docs/make.bat | 35 ---- docs/mkdocs.yml | 29 +++ docs/requirements.in | 4 +- docs/requirements.txt | 44 ++--- docs/solidity-docgen-templates/contract.hbs | 53 +++++ docs/source/api.rst | 16 -- docs/source/conf.py | 90 --------- docs/source/index.rst | 21 -- package.json | 7 + 23 files changed, 361 insertions(+), 526 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 README.md create mode 100644 contracts/stableCoin/standalone/IDoubleProxy.sol create mode 100644 contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol create mode 100644 contracts/stableCoin/standalone/IMWDProxy.sol create mode 100644 contracts/stableCoin/standalone/IStateHolder.sol create mode 100644 contracts/stableCoin/standalone/IUniswapV2Pair.sol create mode 100644 contracts/stableCoin/standalone/IUniswapV2Router.sol delete mode 100644 docs/Makefile delete mode 100644 docs/docs.json delete mode 100644 docs/make.bat create mode 100644 docs/mkdocs.yml create mode 100644 docs/solidity-docgen-templates/contract.hbs delete mode 100644 docs/source/api.rst delete mode 100644 docs/source/conf.py delete mode 100644 docs/source/index.rst diff --git a/.gitignore b/.gitignore index 0177b03..af8ddd5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /**/spa/**/style.css docs/build +docs/md-build # 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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2967def --- /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] and [Solidity Domain for Sphinx]. + +Documentation is generated using [solidity-docgen] and rendered via [mkdocs]. +[solidity-docgen] parses NatSpec and outputs `.md` files inside `docs/md-build` according +to an Handlebars template located at `docs/solidity-docgen-templates/contract.hbs`. + +**NOTE:** Each `.sol` file should contain only one `Interface` or `Contract`. + +To build the documentation: + +```console +yarn docs +``` + +To serve the documentation + +```console +yarn docs:serve +``` + +### mkdocs + +To install [mkdocs] 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 +[solidity-docgen]: https://github.com/OpenZeppelin/solidity-docgen +[mkdocs]: https://www.mkdocs.org/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd811d5 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# unifi + +A DFO protocol powered DeFi set of tools built on top of Uniswap. diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index 6e0c552..d19cef6 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -3,7 +3,8 @@ pragma solidity ^0.6.0; /** - * @title Mint Voting Tokens (unifi) by burning Stable Coin (uSD) // DOCUMENT + * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) // DOCUMENT + * @dev This contract define the logic that is used */ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { diff --git a/contracts/stableCoin/standalone/IDoubleProxy.sol b/contracts/stableCoin/standalone/IDoubleProxy.sol new file mode 100644 index 0000000..5b6c101 --- /dev/null +++ b/contracts/stableCoin/standalone/IDoubleProxy.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.6.0; + +// DOCUMENT +interface IDoubleProxy { + function proxy() external view returns (address); +} diff --git a/contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol b/contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol new file mode 100644 index 0000000..a99e8f2 --- /dev/null +++ b/contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.6.0; + +// DOCUMENT +interface IMVDFunctionalitiesManager { + function isAuthorizedFunctionality(address functionality) external view returns (bool); +} diff --git a/contracts/stableCoin/standalone/IMWDProxy.sol b/contracts/stableCoin/standalone/IMWDProxy.sol new file mode 100644 index 0000000..b4c6d23 --- /dev/null +++ b/contracts/stableCoin/standalone/IMWDProxy.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.6.0; + +// DOCUMENT +interface IMVDProxy { + function getToken() external view returns (address); + + function getMVDFunctionalitiesManagerAddress() external view returns (address); + + function getMVDWalletAddress() external view returns (address); + + function getStateHolderAddress() external view returns (address); + + function submit(string calldata codeName, bytes calldata data) + external + payable + returns (bytes memory returnData); +} diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index a1b352a..7569796 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -156,7 +156,7 @@ interface IStableCoin { ) external returns (uint256 amountA, uint256 amountB); /** - * @dev Rebalance by Credit is triggered when the total amount of source tokens is greater + * @dev Rebalance by Credit is triggered when the total amount of source tokens' value is greater * than uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. * * ===== @@ -172,183 +172,13 @@ interface IStableCoin { ) external returns (uint256 redeemed); /** - * @dev // DOCUMENT - */ - function rebalanceByDebt(uint256 amount) external returns (uint256); -} - -// -----------------------------------------------------------------------------------------------| - -// DOCUMENT -interface IDoubleProxy { - function proxy() external view returns (address); -} - -// -----------------------------------------------------------------------------------------------| - -// DOCUMENT -interface IMVDProxy { - function getToken() external view returns (address); - - function getMVDFunctionalitiesManagerAddress() external view returns (address); - - function getMVDWalletAddress() external view returns (address); - - function getStateHolderAddress() external view returns (address); - - function submit(string calldata codeName, bytes calldata data) - external - payable - returns (bytes memory returnData); -} - -// -----------------------------------------------------------------------------------------------| - -// DOCUMENT -interface IMVDFunctionalitiesManager { - function isAuthorizedFunctionality(address functionality) external view returns (bool); -} - -// -----------------------------------------------------------------------------------------------| - -// DOCUMENT -interface IStateHolder { - function getBool(string calldata varName) external view returns (bool); - - function getUint256(string calldata varName) external view returns (uint256); -} - -// -----------------------------------------------------------------------------------------------| - -/** - * @title Uniswap V2 Router - * @dev Route liquidity back and forth an Uniswap Liquidity Pool. - * For more information see: https://uniswap.org/docs/v2/smart-contracts/router02/ - * - */ -interface IUniswapV2Router { - /** - * https://uniswap.org/docs/v2/smart-contracts/library#getamountsout - * Given an input asset amount and an array of token addresses, calculates all subsequent maximum - * output token amounts by calling getReserves for each pair of token addresses in the path in - * turn, and using these to call getAmountOut. Useful for calculating optimal token amounts - * before calling swap. - */ - function getAmountsOut(uint256 amountIn, address[] calldata path) - external - view - returns (uint256[] memory amounts); - - /** - * @dev Removes liquidity from an ERC-20⇄ERC-20 pool - * - * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity - * - * ===== - * - * @param tokenA A pool token - * @param tokenB A pool token - * @param liquidity The amount of liquidity tokens to remove - * @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 to Recipient of the underlying assets - * @param deadline Unix timestamp after which the transaction will revert - * - * ===== - * - * @return amountA The amount of tokenA received - * @return amountB The amount of tokenB received - * - */ - function removeLiquidity( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external returns (uint256 amountA, uint256 amountB); - - /** - * @dev Add Liquidity to an ERC-20⇄ERC-20 pool - * - * - To cover all possible scenarios, msg.sender should have already given the router an allowance - * of at least amountADesired/amountBDesired on tokenA/tokenB. - * - Always adds assets at the ideal ratio, according to the price when the transaction is executed. - * - If a pool for the passed tokens does not exists, one is created automatically, and exactly - * amountADesired/amountBDesired tokens are added. - * - * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity - * - * ===== - * - * @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. - * @param to Recipient of the underlying assets - * @param deadline Unix timestamp after which the transaction will revert + * @dev Rebalance by Credit is triggered when the total amount of source tokens' value is greater + * than uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. * * ===== * - * @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 - * + * @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 addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) - external - returns ( - uint256 amountA, - uint256 amountB, - uint256 liquidity - ); -} - -// -----------------------------------------------------------------------------------------------| - -// DOCUMENT -/** - * @title Uniswap V2 Pair - */ -interface IUniswapV2Pair { - // DOCUMENT - function decimals() external pure returns (uint8); - - // DOCUMENT - function totalSupply() external view returns (uint256); - - // DOCUMENT - function token0() external view returns (address); - - // DOCUMENT - function token1() external view returns (address); - - // DOCUMENT - function balanceOf(address account) external view returns (uint256); - - // DOCUMENT - function getReserves() - external - view - returns ( - uint112 reserve0, - uint112 reserve1, - uint32 blockTimestampLast - ); + function rebalanceByDebt(uint256 amount) external returns (uint256); } diff --git a/contracts/stableCoin/standalone/IStateHolder.sol b/contracts/stableCoin/standalone/IStateHolder.sol new file mode 100644 index 0000000..9a23fb8 --- /dev/null +++ b/contracts/stableCoin/standalone/IStateHolder.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.6.0; + +// DOCUMENT +interface IStateHolder { + function getBool(string calldata varName) external view returns (bool); + + function getUint256(string calldata varName) external view returns (uint256); +} diff --git a/contracts/stableCoin/standalone/IUniswapV2Pair.sol b/contracts/stableCoin/standalone/IUniswapV2Pair.sol new file mode 100644 index 0000000..7658298 --- /dev/null +++ b/contracts/stableCoin/standalone/IUniswapV2Pair.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.6.0; + +// DOCUMENT +/** + * @title Uniswap V2 Pair + */ +interface IUniswapV2Pair { + // DOCUMENT + function decimals() external pure returns (uint8); + + // DOCUMENT + function totalSupply() external view returns (uint256); + + // DOCUMENT + function token0() external view returns (address); + + // DOCUMENT + function token1() external view returns (address); + + // DOCUMENT + function balanceOf(address account) external view returns (uint256); + + // DOCUMENT + function getReserves() + external + view + returns ( + uint112 reserve0, + uint112 reserve1, + uint32 blockTimestampLast + ); +} diff --git a/contracts/stableCoin/standalone/IUniswapV2Router.sol b/contracts/stableCoin/standalone/IUniswapV2Router.sol new file mode 100644 index 0000000..eb3849b --- /dev/null +++ b/contracts/stableCoin/standalone/IUniswapV2Router.sol @@ -0,0 +1,101 @@ +pragma solidity ^0.6.0; + +/** + * @title Uniswap V2 Router + * @dev Route liquidity back and forth an Uniswap Liquidity Pool. + * For more information see: https://uniswap.org/docs/v2/smart-contracts/router02/ + * + */ +interface IUniswapV2Router { + /** + * https://uniswap.org/docs/v2/smart-contracts/library#getamountsout + * Given an input asset amount and an array of token addresses, calculates all subsequent maximum + * output token amounts by calling getReserves for each pair of token addresses in the path in + * turn, and using these to call getAmountOut. Useful for calculating optimal token amounts + * before calling swap. + */ + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + /** + * @dev Removes liquidity from an ERC-20⇄ERC-20 pool + * + * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity + * + * ===== + * + * @param tokenA A pool token + * @param tokenB A pool token + * @param liquidity The amount of liquidity tokens to remove + * @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 to Recipient of the underlying assets + * @param deadline Unix timestamp after which the transaction will revert + * + * ===== + * + * @return amountA The amount of tokenA received + * @return amountB The amount of tokenB received + * + */ + function removeLiquidity( + address tokenA, + address tokenB, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) external returns (uint256 amountA, uint256 amountB); + + /** + * @dev Add Liquidity to an ERC-20⇄ERC-20 pool + * + * - To cover all possible scenarios, msg.sender should have already given the router an allowance + * of at least amountADesired/amountBDesired on tokenA/tokenB. + * - Always adds assets at the ideal ratio, according to the price when the transaction is executed. + * - If a pool for the passed tokens does not exists, one is created automatically, and exactly + * amountADesired/amountBDesired tokens are added. + * + * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity + * + * ===== + * + * @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. + * @param to Recipient of the underlying assets + * @param deadline Unix timestamp after which the transaction will revert + * + * ===== + * + * @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 addLiquidity( + address tokenA, + address tokenB, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) + external + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ); +} diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 2d45bf6..6c84858 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -4,11 +4,17 @@ pragma solidity ^0.6.0; import "./ERC20.sol"; import "./IStableCoin.sol"; +import "./IMWDFunctionalitiesManager.sol"; +import "./IMWDProxy.sol"; +import "./IDoubleProxy.sol"; +import "./IStateHolder.sol"; +import "./IUniswapV2Pair.sol"; +import "./IUniswapV2Router.sol"; /** * @title StableCoin - * @dev Contract for the "uSD" Stable Coin. It's an ERC20 token extended with the IStableCoin - * interface. + * @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 { // |------------------------------------------------------------------------------------------| diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/docs.json b/docs/docs.json deleted file mode 100644 index b63e6ac..0000000 --- a/docs/docs.json +++ /dev/null @@ -1,132 +0,0 @@ - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IDoubleProxy ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IMVDFunctionalitiesManager ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IMVDProxy ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IStableCoin ======= -Developer Documentation -{ - "details": "Define the interface for the usD", - "kind": "dev", - "methods": - { - "allowedPairs()": - { - "details": "Get the list of allowed Uniswap pairs", - "returns": - { - "_0": "List of allowed Uniswap pairs" - } - }, - "availableToMint()": - { - "details": "Get the amount of available mintable token" - }, - "calculateRebalanceByDebtReward(uint256)": - { - "details": "@param burnt amount of of uSD burnt" - }, - "differences()": - { - "details": "GET" - }, - "doubleProxy()": - { - "details": "Get the address for the doubleProxy smart contract" - }, - "fromTokenToStable(address,uint256)": - { - "details": "Convert from one of the pooled token to uSD", - "params": - { - "amount": "Of token to be converted", - "tokenAddress": "Address of the token to convert" - }, - "returns": - { - "_0": "Amount of uSD tokens" - } - }, - "init(string,string,address,address[],uint256[],uint256[],uint256[])": - { - "details": "Constructor signature", - "params": - { - "allowedPairs": "list of Uniswap Pairs to be set as whitelisted source tokens", - "doubleProxy": "address for the DoubleProxy", - "mintables": "max amount of mintables inside a timeWindow", - "name": "name of the StableCoin ERC20 token", - "rebalanceRewardMultiplier": "multiplier used to compute how many unifi tokens to mint during uSD rebalance", - "symbol": "ticker for the StableCoin ERC20 token", - "timeWindows": "time windows inside which some time-delimited operations can be performed" - } - }, - "setAllowedPairs(address[])": - { - "details": "Set the whitelisted Uniswap pairs", - "params": - { - "newAllowedPairs": "list of Uniswap pairs to be whitelisted" - } - }, - "setDoubleProxy(address)": - { - "details": "Set a new DoubleProxy", - "params": - { - "newDoubleProxy": "new DoubleProxy to set" - } - }, - "tierData()": - { - "details": "Get all tiers of data of the carried context" - } - }, - "title": "Interface for the \"uSD\" AKA \"uniswap State Dollar\", Unifi stablecoin.", - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IStateHolder ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IUniswapV2Pair ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "title": "Interface", - "version": 1 -} - -======= ../contracts/stableCoin/standalone/IStableCoin.sol:IUniswapV2Router ======= -Developer Documentation -{ - "kind": "dev", - "methods": {}, - "version": 1 -} diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 6247f7e..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 0000000..b4829c9 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,29 @@ +site_name: Unifi Docs +docs_dir: md-build +site_dir: build +permalink: True +nav: + - Home: README.md + - Contributing: CONTRIBUTING.md + - API: + - Stable Coin: + - Address: stableCoin/Address.md + - Context: stableCoin/Context.md + - ERC20: stableCoin/ERC20.md + - IDoubleProxy: stableCoin/IDoubleProxy.md + - IERC20: stableCoin/IERC20.md + - IMWDFunctionalitiesManager: stableCoin/IMWDFunctionalitiesManager.md + - IMWDProxy: stableCoin/IMWDProxy.md + - IStableCoin: stableCoin/IStableCoin.md + - IStateHolder: stableCoin/IStateHolder.md + - IUniswapV2Pair: stableCoin/IUniswapV2Pair.md + - IUniswapV2Router: stableCoin/IUniswapV2Router.md + - SafeMath: stableCoin/SafeMath.md + - StableCoin: stableCoin/StableCoin.md +theme: + name: readthedocs + highlightjs: true + hljs_languages: + - yaml + - typescript + - javascript diff --git a/docs/requirements.in b/docs/requirements.in index 08cf9e8..016bb16 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -1,3 +1 @@ -sphinx -sphinxcontrib-soliditydomain -sphinx-rtd-theme +mkdocs diff --git a/docs/requirements.txt b/docs/requirements.txt index d80e570..d9819f7 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,34 +4,18 @@ # # pip-compile requirements.in # -alabaster==0.7.12 # via sphinx -antlr4-python3-runtime==4.7.1 # via sphinxcontrib-soliditydomain -babel==2.8.0 # via sphinx -certifi==2020.6.20 # via requests -chardet==3.0.4 # via requests -docutils==0.16 # via sphinx -idna==2.10 # via requests -imagesize==1.2.0 # via sphinx -jinja2==2.11.2 # via sphinx +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 -packaging==20.4 # via sphinx -peewee==3.13.3 # via sphinxcontrib-soliditydomain -pygments==2.6.1 # via sphinx -pyparsing==2.4.7 # via packaging -pytz==2020.1 # via babel -requests==2.24.0 # via sphinx -six==1.15.0 # via packaging -snowballstemmer==2.0.0 # via sphinx -sphinx-rtd-theme==0.5.0 # via -r requirements.in -sphinx==3.1.2 # via -r requirements.in, sphinx-rtd-theme -sphinxcontrib-applehelp==1.0.2 # via sphinx -sphinxcontrib-devhelp==1.0.2 # via sphinx -sphinxcontrib-htmlhelp==1.0.3 # via sphinx -sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 # via sphinx -sphinxcontrib-serializinghtml==1.1.4 # via sphinx -sphinxcontrib-soliditydomain==0.5.1 # via -r requirements.in -urllib3==1.25.10 # via requests - -# The following packages are considered to be unsafe in a requirements file: -# setuptools +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..f934295 --- /dev/null +++ b/docs/solidity-docgen-templates/contract.hbs @@ -0,0 +1,53 @@ +# {{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}}` +#### Description +{{#if natspec.devdoc}}{{natspec.devdoc}}{{else}}No description{{/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}})` +#### Description +{{#if natspec.devdoc}}{{natspec.devdoc}}{{else}}No description{{/if}} +{{#if natspec.params}} +#### Parameters: +{{#natspec.params}} +- `{{param}}`: {{description}} +{{/natspec.params}} +{{/if}} +{{/ownEvents}} diff --git a/docs/source/api.rst b/docs/source/api.rst deleted file mode 100644 index 90b33a5..0000000 --- a/docs/source/api.rst +++ /dev/null @@ -1,16 +0,0 @@ -############# -API Reference -############# - - -.. autosolinterface:: IStableCoin - :members: - -.. autosolinterface:: IDoubleProxy - :members: - -.. autosolinterface:: IUniswapV2Router - :members: - -.. autosolinterface:: IUniswapV2Pair - :members: diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index c52ed61..0000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,90 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# - -import os -import sys - -sys.path.insert(0, os.path.abspath(".")) - - -# -- Project information ----------------------------------------------------- - -project = "unifi" -copyright = "2020, unifi" -author = "unifi" - - -# The short X.Y version -version = "0.5.0" -# The full version, including alpha/beta/rc tags -release = "0.5.0" - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinxcontrib.soliditydomain", - "sphinx.ext.intersphinx", -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - -# -- Options for HTML output ------------------------------------------------- - -# Logo -html_logo = "" - - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "sphinx_rtd_theme" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - "display_version": True, - "sticky_navigation": True, - "collapse_navigation": False, - "navigation_depth": 4, - "logo_only": True, -} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -html_css_files = ["css/custom.css"] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index e37646e..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. unifi documentation master file, created by - sphinx-quickstart on Thu Aug 6 20:57:06 2020. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to unifi's documentation! -=================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents:' - - api - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/package.json b/package.json index feeb550..d8a57f0 100644 --- a/package.json +++ b/package.json @@ -10,5 +10,12 @@ "prettier-plugin-solidity": "^1.0.0-alpha.56", "solc": "^0.7.0", "solidity-docgen": "^0.5.4" + }, + "scripts": { + "docs": "yarn docs:clean && yarn docs:docgen && yarn docs:mkdocs", + "docs:clean": "rm -r docs/{md-build,build}", + "docs:docgen": "cd docs && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build && mv md-build/stableCoin/standalone/* md-build/stableCoin && rm -r md-build/stableCoin/standalone/", + "docs:mkdocs:build": "cd docs && mkdocs build", + "docs:mkdocs:serve": "yarn docs:docgen && cd docs && mkdocs serve" } } From b386943cce7a2cf276acc992897b379581ff9fd4 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Wed, 26 Aug 2020 22:36:54 +0200 Subject: [PATCH 07/19] Scripting is hard --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d8a57f0..a7ab3bb 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "solidity-docgen": "^0.5.4" }, "scripts": { - "docs": "yarn docs:clean && yarn docs:docgen && yarn docs:mkdocs", + "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:docgen": "cd docs && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build && mv md-build/stableCoin/standalone/* md-build/stableCoin && rm -r md-build/stableCoin/standalone/", "docs:mkdocs:build": "cd docs && mkdocs build", From b3e2e12444d555ae2354b03669443e3d4bbfb910 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Thu, 27 Aug 2020 00:14:23 +0200 Subject: [PATCH 08/19] Remove non unifi/usd contracts from docs --- CONTRIBUTING.md | 2 +- README.md | 9 +++ contracts/stableCoin/microservices/IERC20.sol | 7 +++ .../IMVDFunctionalitiesManager.sol | 5 ++ .../stableCoin/microservices/IMVDProxy.sol | 21 +++++++ .../stableCoin/microservices/IStateHolder.sol | 11 ++++ ...VotingTokensForStableCoinFunctionality.sol | 57 +++---------------- ...ger.sol => IMVDFunctionalitiesManager.sol} | 0 .../{IMWDProxy.sol => IMVDProxy.sol} | 0 .../stableCoin/standalone/IStableCoin.sol | 26 ++------- .../stableCoin/standalone/StableCoin.sol | 4 +- docs/mkdocs.yml | 21 +++---- docs/solidity-docgen-templates/contract.hbs | 6 +- package.json | 3 +- 14 files changed, 81 insertions(+), 91 deletions(-) create mode 100644 contracts/stableCoin/microservices/IERC20.sol create mode 100644 contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol create mode 100644 contracts/stableCoin/microservices/IMVDProxy.sol create mode 100644 contracts/stableCoin/microservices/IStateHolder.sol rename contracts/stableCoin/{ => microservices}/MintNewVotingTokensForStableCoinFunctionality.sol (65%) rename contracts/stableCoin/standalone/{IMWDFunctionalitiesManager.sol => IMVDFunctionalitiesManager.sol} (100%) rename contracts/stableCoin/standalone/{IMWDProxy.sol => IMVDProxy.sol} (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2967def..bfddaf5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,7 +39,7 @@ to an Handlebars template located at `docs/solidity-docgen-templates/contract.hb To build the documentation: ```console -yarn docs +yarn docs:build ``` To serve the documentation diff --git a/README.md b/README.md index cd811d5..cf1c83d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ # unifi A DFO protocol powered DeFi set of tools built on top of Uniswap. + +## Built With + +- DFO Protocol +- [Uniswap V2 Protocol] +- [Open Zeppelin ERC20 Token Contracts] + +[Uniswap V2 Protocol]: https://discordapp.com/channels/@me/741405541884100760/748296081745379339 +[Open Zeppelin ERC20 Token Contracts]: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20 diff --git a/contracts/stableCoin/microservices/IERC20.sol b/contracts/stableCoin/microservices/IERC20.sol new file mode 100644 index 0000000..ac0d35e --- /dev/null +++ b/contracts/stableCoin/microservices/IERC20.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.6.0; + +interface IERC20 { + function mint(uint256 amount) external; + + function balanceOf(address account) external view returns (uint256); +} diff --git a/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol new file mode 100644 index 0000000..72d2e2d --- /dev/null +++ b/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.6.0; + +interface IMVDFunctionalitiesManager { + function isAuthorizedFunctionality(address functionality) external view returns (bool); +} diff --git a/contracts/stableCoin/microservices/IMVDProxy.sol b/contracts/stableCoin/microservices/IMVDProxy.sol new file mode 100644 index 0000000..a3021d5 --- /dev/null +++ b/contracts/stableCoin/microservices/IMVDProxy.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.6.0; + +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; +} diff --git a/contracts/stableCoin/microservices/IStateHolder.sol b/contracts/stableCoin/microservices/IStateHolder.sol new file mode 100644 index 0000000..a61540d --- /dev/null +++ b/contracts/stableCoin/microservices/IStateHolder.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.6.0; + +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 getBool(string calldata varName) external view returns (bool); +} diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol similarity index 65% rename from contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol rename to contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol index d19cef6..ff4b023 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol @@ -2,9 +2,14 @@ pragma solidity ^0.6.0; +import "./IERC20.sol"; +import "./IMVDFunctionalitiesManager.sol"; +import "./IMVDProxy.sol"; +import "./IStateHolder.sol"; + /** - * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) // DOCUMENT - * @dev This contract define the logic that is used + * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) + * @dev This contract adds unifi minting capabilies to uSD */ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { @@ -83,51 +88,3 @@ contract MintNewVotingTokensForStableCoinFunctionality { 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; -} - -// -------------------------------------------------------------------------------------- - -interface IMVDFunctionalitiesManager { - 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 getBool(string calldata varName) external view returns (bool); -} - -// -------------------------------------------------------------------------------------- - -interface IERC20 { - function mint(uint256 amount) external; - - function balanceOf(address account) external view returns (uint256); -} diff --git a/contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol similarity index 100% rename from contracts/stableCoin/standalone/IMWDFunctionalitiesManager.sol rename to contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol diff --git a/contracts/stableCoin/standalone/IMWDProxy.sol b/contracts/stableCoin/standalone/IMVDProxy.sol similarity index 100% rename from contracts/stableCoin/standalone/IMWDProxy.sol rename to contracts/stableCoin/standalone/IMVDProxy.sol diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 7569796..6aef2f0 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -38,9 +38,9 @@ interface IStableCoin { function allowedPairs() external view returns (address[] memory); /** - * @return The amount of available mintable token + * @return mintable The amount of available mintable token */ - function availableToMint() external view returns (uint256); + function availableToMint() external view returns (uint256 mintable); // DOCUMENT function differences() external view returns (uint256, uint256); @@ -79,24 +79,18 @@ interface IStableCoin { // |------------------------------------------------------------------------------------------| /** - * @dev // DOCUMENT - * - * ===== + * @dev Compute the reward of the rebalanceByDebt() operation. * * @param burnt amount of of uSD burnt */ - function calculateRebalanceByDebtReward(uint256 burnt) external view returns (uint256); + 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) @@ -108,8 +102,6 @@ interface IStableCoin { * 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) @@ -120,8 +112,6 @@ interface IStableCoin { * @param amountBMin Bounds the extent to which the A/B price can go up before the transaction reverts. * Must be <= amountBDesired * - * ===== - * * @return Amount of freshly minted uSD token */ function mint( @@ -136,14 +126,10 @@ interface IStableCoin { * Mint logic of the StableCoin. * @dev Mint the uSD token * - * ===== - * * @param pairIndex Index of the pair inside the allowedPairs array * @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 amountA The amount of tokenA received * @return amountB The amount of tokenB received * @@ -159,8 +145,6 @@ interface IStableCoin { * @dev Rebalance by Credit is triggered when the total amount of source tokens' value 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 */ @@ -175,8 +159,6 @@ interface IStableCoin { * @dev Rebalance by Credit is triggered when the total amount of source tokens' value 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 */ diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 6c84858..bff3f4c 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -4,8 +4,8 @@ pragma solidity ^0.6.0; import "./ERC20.sol"; import "./IStableCoin.sol"; -import "./IMWDFunctionalitiesManager.sol"; -import "./IMWDProxy.sol"; +import "./IMVDFunctionalitiesManager.sol"; +import "./IMVDProxy.sol"; import "./IDoubleProxy.sol"; import "./IStateHolder.sol"; import "./IUniswapV2Pair.sol"; diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b4829c9..739f0a8 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -7,19 +7,14 @@ nav: - Contributing: CONTRIBUTING.md - API: - Stable Coin: - - Address: stableCoin/Address.md - - Context: stableCoin/Context.md - - ERC20: stableCoin/ERC20.md - - IDoubleProxy: stableCoin/IDoubleProxy.md - - IERC20: stableCoin/IERC20.md - - IMWDFunctionalitiesManager: stableCoin/IMWDFunctionalitiesManager.md - - IMWDProxy: stableCoin/IMWDProxy.md - - IStableCoin: stableCoin/IStableCoin.md - - IStateHolder: stableCoin/IStateHolder.md - - IUniswapV2Pair: stableCoin/IUniswapV2Pair.md - - IUniswapV2Router: stableCoin/IUniswapV2Router.md - - SafeMath: stableCoin/SafeMath.md - - StableCoin: stableCoin/StableCoin.md + - 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 + - Microservices: + - MintNewVotingTokensForStableCoinFunctionality: stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.md + theme: name: readthedocs highlightjs: true diff --git a/docs/solidity-docgen-templates/contract.hbs b/docs/solidity-docgen-templates/contract.hbs index f934295..364cddd 100644 --- a/docs/solidity-docgen-templates/contract.hbs +++ b/docs/solidity-docgen-templates/contract.hbs @@ -22,8 +22,9 @@ {{#if (or (eq visibility "public") (eq visibility "external"))}} ### Function: {{name}} `{{name}}({{args}}){{#if outputs}} → {{outputs}}{{/if}}` +{{#if natspec.devdoc}} #### Description -{{#if natspec.devdoc}}{{natspec.devdoc}}{{else}}No description{{/if}} +{{natspec.devdoc}}{{else}}{{/if}} {{#if natspec.params}} #### Parameters: {{#natspec.params}} @@ -42,8 +43,9 @@ {{#ownEvents}} ### Event: {{name}} `{{name}}({{args}})` +{{#if natspec.devdoc}} #### Description -{{#if natspec.devdoc}}{{natspec.devdoc}}{{else}}No description{{/if}} +{{natspec.devdoc}}{{else}}{{/if}} {{#if natspec.params}} #### Parameters: {{#natspec.params}} diff --git a/package.json b/package.json index a7ab3bb..20de3cc 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "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:docgen": "cd docs && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build && mv md-build/stableCoin/standalone/* md-build/stableCoin && rm -r md-build/stableCoin/standalone/", + "docs:serve": "yarn docs:docgen && yarn docs:mkdocs:serve", + "docs:docgen": "cd docs && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build", "docs:mkdocs:build": "cd docs && mkdocs build", "docs:mkdocs:serve": "yarn docs:docgen && cd docs && mkdocs serve" } From 90b3ca7dd6aeb15d7125d4227a64596f0c2fe0e9 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Thu, 27 Aug 2020 01:23:15 +0200 Subject: [PATCH 09/19] Prepare for release --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cf1c83d..5761c90 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ A DFO protocol powered DeFi set of tools built on top of Uniswap. ## Built With -- DFO Protocol -- [Uniswap V2 Protocol] -- [Open Zeppelin ERC20 Token Contracts] -[Uniswap V2 Protocol]: https://discordapp.com/channels/@me/741405541884100760/748296081745379339 -[Open Zeppelin ERC20 Token Contracts]: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20 +- dfohub +- Uniswap V2 Protocol +- Open Zeppelin ERC20 Token Contracts From c042df3b2c5e6c5e034e864558a29a1139bc8c85 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Thu, 27 Aug 2020 01:57:00 +0200 Subject: [PATCH 10/19] Add lowercasing script --- docs/to_lowercase.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/to_lowercase.sh diff --git a/docs/to_lowercase.sh b/docs/to_lowercase.sh new file mode 100644 index 0000000..80ec06f --- /dev/null +++ b/docs/to_lowercase.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +sed -i -E 's/(\(#.*)/\L\1\E/g' md-build/stableCoin/**/*.md From 0f92f3a6a90f036f36c4f24ff5d04a123e5618e0 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Fri, 28 Aug 2020 22:44:24 +0200 Subject: [PATCH 11/19] Update docs --- contracts/stableCoin/microservices/IERC20.sol | 2 +- .../IMVDFunctionalitiesManager.sol | 2 +- .../stableCoin/microservices/IMVDProxy.sol | 2 +- .../stableCoin/microservices/IStateHolder.sol | 4 +- ...VotingTokensForStableCoinFunctionality.sol | 2 +- contracts/stableCoin/standalone/Address.sol | 2 +- contracts/stableCoin/standalone/Context.sol | 2 +- contracts/stableCoin/standalone/ERC20.sol | 2 +- .../stableCoin/standalone/IDoubleProxy.sol | 2 +- contracts/stableCoin/standalone/IERC20.sol | 2 +- .../standalone/IMVDFunctionalitiesManager.sol | 2 +- contracts/stableCoin/standalone/IMVDProxy.sol | 2 +- .../stableCoin/standalone/IStableCoin.sol | 38 +++++++++++-------- .../stableCoin/standalone/IStateHolder.sol | 2 +- .../stableCoin/standalone/IUniswapV2Pair.sol | 2 +- .../standalone/IUniswapV2Router.sol | 2 +- contracts/stableCoin/standalone/SafeMath.sol | 2 +- .../stableCoin/standalone/StableCoin.sol | 4 +- docs/to_lowercase.sh | 2 +- package.json | 2 +- 20 files changed, 44 insertions(+), 36 deletions(-) mode change 100644 => 100755 docs/to_lowercase.sh diff --git a/contracts/stableCoin/microservices/IERC20.sol b/contracts/stableCoin/microservices/IERC20.sol index ac0d35e..28bb3b9 100644 --- a/contracts/stableCoin/microservices/IERC20.sol +++ b/contracts/stableCoin/microservices/IERC20.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; interface IERC20 { function mint(uint256 amount) external; diff --git a/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol index 72d2e2d..64d9e03 100644 --- a/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol +++ b/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; interface IMVDFunctionalitiesManager { function isAuthorizedFunctionality(address functionality) external view returns (bool); diff --git a/contracts/stableCoin/microservices/IMVDProxy.sol b/contracts/stableCoin/microservices/IMVDProxy.sol index a3021d5..fbfd67c 100644 --- a/contracts/stableCoin/microservices/IMVDProxy.sol +++ b/contracts/stableCoin/microservices/IMVDProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; interface IMVDProxy { function getToken() external view returns (address); diff --git a/contracts/stableCoin/microservices/IStateHolder.sol b/contracts/stableCoin/microservices/IStateHolder.sol index a61540d..a53be3d 100644 --- a/contracts/stableCoin/microservices/IStateHolder.sol +++ b/contracts/stableCoin/microservices/IStateHolder.sol @@ -1,4 +1,6 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; interface IStateHolder { function clear(string calldata varName) diff --git a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol index ff4b023..3574a15 100644 --- a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; import "./IERC20.sol"; import "./IMVDFunctionalitiesManager.sol"; diff --git a/contracts/stableCoin/standalone/Address.sol b/contracts/stableCoin/standalone/Address.sol index 6b28275..4af9fb8 100644 --- a/contracts/stableCoin/standalone/Address.sol +++ b/contracts/stableCoin/standalone/Address.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** * @dev Collection of functions related to the address type diff --git a/contracts/stableCoin/standalone/Context.sol b/contracts/stableCoin/standalone/Context.sol index 97c73c4..a193e82 100644 --- a/contracts/stableCoin/standalone/Context.sol +++ b/contracts/stableCoin/standalone/Context.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** * @dev Provides information about the current execution context, including the diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol index 126be42..cddefcf 100644 --- a/contracts/stableCoin/standalone/ERC20.sol +++ b/contracts/stableCoin/standalone/ERC20.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; import "./Context.sol"; import "./IERC20.sol"; diff --git a/contracts/stableCoin/standalone/IDoubleProxy.sol b/contracts/stableCoin/standalone/IDoubleProxy.sol index 5b6c101..0ddd2d2 100644 --- a/contracts/stableCoin/standalone/IDoubleProxy.sol +++ b/contracts/stableCoin/standalone/IDoubleProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; // DOCUMENT interface IDoubleProxy { diff --git a/contracts/stableCoin/standalone/IERC20.sol b/contracts/stableCoin/standalone/IERC20.sol index 82708eb..841d27a 100644 --- a/contracts/stableCoin/standalone/IERC20.sol +++ b/contracts/stableCoin/standalone/IERC20.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. diff --git a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol index a99e8f2..c68f7c5 100644 --- a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol +++ b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; // DOCUMENT interface IMVDFunctionalitiesManager { diff --git a/contracts/stableCoin/standalone/IMVDProxy.sol b/contracts/stableCoin/standalone/IMVDProxy.sol index b4c6d23..83657ea 100644 --- a/contracts/stableCoin/standalone/IMVDProxy.sol +++ b/contracts/stableCoin/standalone/IMVDProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; // DOCUMENT interface IMVDProxy { diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 6aef2f0..ba8745f 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** - * @title Interface for the "uSD" AKA "uniswap State Dollar", Unifi stablecoin. - * @dev Define the interface for the usD + * @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 { /** @@ -14,7 +19,7 @@ interface IStableCoin { * @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 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 */ @@ -81,17 +86,17 @@ interface IStableCoin { /** * @dev Compute the reward of the rebalanceByDebt() operation. * - * @param burnt amount of of uSD burnt + * @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 + * @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 + * @return Amount of $uSD tokens */ function fromTokenToStable(address tokenAddress, uint256 amount) external @@ -100,7 +105,7 @@ interface IStableCoin { /** * Mint logic of the StableCoin. - * @dev Mint the uSD token + * @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 <= @@ -112,7 +117,7 @@ interface IStableCoin { * @param amountBMin Bounds the extent to which the A/B price can go up before the transaction reverts. * Must be <= amountBDesired * - * @return Amount of freshly minted uSD token + * @return Amount of freshly minted $uSD token */ function mint( uint256 pairIndex, @@ -124,7 +129,7 @@ interface IStableCoin { /** * Mint logic of the StableCoin. - * @dev Mint the uSD token + * @dev Mint the $uSD token * * @param pairIndex Index of the pair inside the allowedPairs array * @param amountAMin The minimum amount of tokenA that must be received for the transaction not to revert @@ -142,8 +147,8 @@ interface IStableCoin { ) external returns (uint256 amountA, uint256 amountB); /** - * @dev Rebalance by Credit is triggered when the total amount of source tokens' value is greater - * than uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. + * @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 @@ -156,11 +161,12 @@ interface IStableCoin { ) external returns (uint256 redeemed); /** - * @dev Rebalance by Credit is triggered when the total amount of source tokens' value is greater - * than uSD circulating supply. Rebalancing is done by withdrawing the excess from the pool. + * @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 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 + * @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); } diff --git a/contracts/stableCoin/standalone/IStateHolder.sol b/contracts/stableCoin/standalone/IStateHolder.sol index 9a23fb8..c3b0e3f 100644 --- a/contracts/stableCoin/standalone/IStateHolder.sol +++ b/contracts/stableCoin/standalone/IStateHolder.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; // DOCUMENT interface IStateHolder { diff --git a/contracts/stableCoin/standalone/IUniswapV2Pair.sol b/contracts/stableCoin/standalone/IUniswapV2Pair.sol index 7658298..2a1c7b3 100644 --- a/contracts/stableCoin/standalone/IUniswapV2Pair.sol +++ b/contracts/stableCoin/standalone/IUniswapV2Pair.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; // DOCUMENT /** diff --git a/contracts/stableCoin/standalone/IUniswapV2Router.sol b/contracts/stableCoin/standalone/IUniswapV2Router.sol index eb3849b..ae81a16 100644 --- a/contracts/stableCoin/standalone/IUniswapV2Router.sol +++ b/contracts/stableCoin/standalone/IUniswapV2Router.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** * @title Uniswap V2 Router diff --git a/contracts/stableCoin/standalone/SafeMath.sol b/contracts/stableCoin/standalone/SafeMath.sol index b2e90e8..541864b 100644 --- a/contracts/stableCoin/standalone/SafeMath.sol +++ b/contracts/stableCoin/standalone/SafeMath.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index bff3f4c..6d5a952 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.7.0; import "./ERC20.sol"; import "./IStableCoin.sol"; @@ -13,7 +13,7 @@ import "./IUniswapV2Router.sol"; /** * @title StableCoin - * @dev Contract for the "uSD" Stable Coin. + * @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 { diff --git a/docs/to_lowercase.sh b/docs/to_lowercase.sh old mode 100644 new mode 100755 index 80ec06f..b7beca3 --- a/docs/to_lowercase.sh +++ b/docs/to_lowercase.sh @@ -1,3 +1,3 @@ #! /bin/bash -sed -i -E 's/(\(#.*)/\L\1\E/g' md-build/stableCoin/**/*.md +sed -i -E 's/((#.*)/L1E/g' md-build/stableCoin/**/*.md diff --git a/package.json b/package.json index 20de3cc..aa8b0b3 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "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 && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build", + "docs:docgen": "cd docs && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build && ./to_lowercase.sh", "docs:mkdocs:build": "cd docs && mkdocs build", "docs:mkdocs:serve": "yarn docs:docgen && cd docs && mkdocs serve" } From 44aba835fd37de394ba94685c9bd6e8ca55296cf Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 29 Aug 2020 19:16:43 +0200 Subject: [PATCH 12/19] Update .gitignore to accept unifi-docs as a submodule --- .gitignore | 1 - .gitmodules | 3 +++ docs/build | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 160000 docs/build diff --git a/.gitignore b/.gitignore index af8ddd5..3193fc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ /**/.vscode /**/spa/**/style.css -docs/build docs/md-build # Created by 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/docs/build b/docs/build new file mode 160000 index 0000000..5d81cd6 --- /dev/null +++ b/docs/build @@ -0,0 +1 @@ +Subproject commit 5d81cd62623c23ad5008d45145c318616b2d6511 From 54a4cf0fa7b6a9be17b3df6b7861a4a670fc2057 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 29 Aug 2020 19:47:18 +0200 Subject: [PATCH 13/19] Update docs --- docs/build | 2 +- docs/to_lowercase.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/build b/docs/build index 5d81cd6..32f71b7 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit 5d81cd62623c23ad5008d45145c318616b2d6511 +Subproject commit 32f71b734df8410d3587f7858c3df35a43682896 diff --git a/docs/to_lowercase.sh b/docs/to_lowercase.sh index b7beca3..c789630 100755 --- a/docs/to_lowercase.sh +++ b/docs/to_lowercase.sh @@ -1,3 +1,3 @@ #! /bin/bash -sed -i -E 's/((#.*)/L1E/g' md-build/stableCoin/**/*.md +sed -i -E 's/((#.*))/L1E/g' md-build/stableCoin/**/*.md From ddbb1b03dc858f23a8fda48039857a88703dc9de Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sun, 30 Aug 2020 15:07:05 +0200 Subject: [PATCH 14/19] Fix to_lowercase.sh script --- docs/to_lowercase.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/to_lowercase.sh b/docs/to_lowercase.sh index c789630..80ec06f 100755 --- a/docs/to_lowercase.sh +++ b/docs/to_lowercase.sh @@ -1,3 +1,3 @@ #! /bin/bash -sed -i -E 's/((#.*))/L1E/g' md-build/stableCoin/**/*.md +sed -i -E 's/(\(#.*)/\L\1\E/g' md-build/stableCoin/**/*.md From 40cf5bb6908a6b83496ac0ba4acd85c820059ad8 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sun, 30 Aug 2020 15:11:32 +0200 Subject: [PATCH 15/19] Update docs --- docs/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build b/docs/build index 32f71b7..4910af7 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit 32f71b734df8410d3587f7858c3df35a43682896 +Subproject commit 4910af7fdd9d8cbfd719c65ea83dba87dca26a95 From fb94d43195dae6ffc34a64540d2b60c117d06be3 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 1 Sep 2020 00:43:08 +0200 Subject: [PATCH 16/19] WIP --- .../farming/IUnifiedStableFarming.sol | 102 ++++++++++++----- .../farming/UnifiedStableFarming.sol | 107 +++++++++++------- .../stableCoin/standalone/IStableCoin.sol | 5 +- .../stableCoin/standalone/StableCoin.sol | 5 +- 4 files changed, 143 insertions(+), 76 deletions(-) diff --git a/contracts/stableCoin/farming/IUnifiedStableFarming.sol b/contracts/stableCoin/farming/IUnifiedStableFarming.sol index b811263..29a1bcd 100644 --- a/contracts/stableCoin/farming/IUnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/IUnifiedStableFarming.sol @@ -1,33 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface IUnifiedStableFarming { - - //Earn pumping uSD - Means burn uSD then swap the chosen Uniswap Pool tokens for uSD - function earnByPump( - address stableCoinAddress, - uint256 pairIndex, - uint256 pairAmount, - uint256 amount0, - uint256 amount1, - address tokenAddress, - uint256 tokenValue) external; - - //Earn dumping uSD - Means mint uSD then swap uSD for the chosen Uniswap Pool tokens - function earnByDump( - address stableCoinAddress, - uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min, - uint256[] calldata tokenIndices, - uint256[] calldata stableCoinAmounts) external; -} +pragma solidity ^0.6.0; interface IStableCoin { - function allowedPairs() external view returns (address[] memory); function fromTokenToStable(address tokenAddress, uint256 amount) @@ -53,18 +28,85 @@ interface IStableCoin { interface IUniswapV2Pair { function token0() external view returns (address); + function token1() external view returns (address); } interface IUniswapV2Router { - 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 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); } 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); +} + +interface IUnifiedStableFarming { + /** + * @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 + * @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 amountAMin, + uint256 amountBMin, + address tokenAddress, + uint256 tokenValue + ) external; + + /** + * @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 amountA, + uint256 amountB, + uint256 amountAMin, + uint256 amountBMin, + uint256[] calldata tokenIndices, + uint256[] calldata stableCoinAmounts + ) external; +} diff --git a/contracts/stableCoin/farming/UnifiedStableFarming.sol b/contracts/stableCoin/farming/UnifiedStableFarming.sol index c5a063e..1b6999a 100644 --- a/contracts/stableCoin/farming/UnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/UnifiedStableFarming.sol @@ -1,46 +1,61 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.6.0; import "./IUnifiedStableFarming.sol"; contract UnifiedStableFarming is IUnifiedStableFarming { - address - private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; + address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; - //Earn pumping uSD - Means burn uSD then swap the chosen Uniswap Pool tokens for uSD + /** + * @inheritdoc IUnifiedStableFarming + */ function earnByPump( address stableCoinAddress, uint256 pairIndex, uint256 pairAmount, - uint256 amount0, - uint256 amount1, + uint256 amountAMin, + uint256 amountBMin, address tokenAddress, uint256 tokenValue ) public override { require( _isValidPairToken(stableCoinAddress, tokenAddress), - "Choosen token address is not in a valid pair" - ); - _transferToMeAndCheckAllowance( - tokenAddress, - tokenValue, - UNISWAP_V2_ROUTER + "Chosen token address is not in a valid pair" ); + // Transfer stablecoin to the contract + _transferToMeAndCheckAllowance(tokenAddress, tokenValue, UNISWAP_V2_ROUTER); + // Swap stablecoin for $uSD uint256 stableCoinAmount = _swap( tokenAddress, stableCoinAddress, tokenValue, address(this) ); - (uint256 return0, uint256 return1) = IStableCoin(stableCoinAddress) - .burn(pairIndex, pairAmount, amount0, amount1); - (address token0, address token1, ) = _getPairData( - stableCoinAddress, - pairIndex + // Swap stablecoin for $uSD + (uint256 returnA, uint256 returnB) = IStableCoin(stableCoinAddress).burn( + pairIndex, + pairAmount, + amountA, + amountB ); - require(_isPumpOK(stableCoinAddress, tokenAddress, tokenValue, token0, return0, token1, return1, stableCoinAmount), "Values are not coherent"); - _flushToSender(token0, token1, stableCoinAddress); + (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); + // Check that the pump was successful + require( + _isPumpOK( + stableCoinAddress, + tokenAddress, + tokenValue, + tokenA, + returnA, + tokenB, + returnB, + stableCoinAmount + ), + "Values are not coherent" + ); + // Send the tokens back to their owner + _flushToSender(tokenA, tokenB, stableCoinAddress); } function _isPumpOK( @@ -61,14 +76,16 @@ contract UnifiedStableFarming is IUnifiedStableFarming { return tokenValueInStable >= cumulative; } - //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 { @@ -76,23 +93,20 @@ 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 - ); - IStableCoin(stableCoinAddress).mint( - pairIndex, - amount0, - amount1, - amount0Min, - amount1Min + amountA, + amountB ); + // Mint $uSD + IStableCoin(stableCoinAddress).mint(pairIndex, amount0, amount1, amount0Min, amount1Min); + // 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, @@ -101,6 +115,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { msg.sender ); } + // Send the tokens back to their owner _flushToSender(token0, token1, stableCoinAddress); } @@ -110,10 +125,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { uint256 amount0, uint256 amount1 ) private { - (address token0, address token1, ) = _getPairData( - stableCoinAddress, - pairIndex - ); + (address token0, address token1, ) = _getPairData(stableCoinAddress, pairIndex); IERC20(token0).transferFrom(msg.sender, address(this), amount0); IERC20(token1).transferFrom(msg.sender, address(this), amount1); } @@ -128,8 +140,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { ) { IUniswapV2Pair pair = IUniswapV2Pair( - pairAddress = IStableCoin(stableCoinAddress) - .allowedPairs()[pairIndex] + pairAddress = IStableCoin(stableCoinAddress).allowedPairs()[pairIndex] ); token0 = pair.token0(); token1 = pair.token1(); @@ -146,6 +157,9 @@ contract UnifiedStableFarming is IUnifiedStableFarming { } } + /** + * @dev Transfer token to the smart contract + */ function _transferToMeAndCheckAllowance( address tokenAddress, uint256 value, @@ -176,6 +190,9 @@ contract UnifiedStableFarming is IUnifiedStableFarming { _flushToSender(token2); } + /** + * @dev Send token to the address calling this contract + */ function _flushToSender(address tokenAddress) private { if (tokenAddress == address(0)) { return; @@ -187,6 +204,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, @@ -215,8 +239,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { view returns (bool) { - address[] memory allowedPairs = IStableCoin(stableCoinAddress) - .allowedPairs(); + address[] memory allowedPairs = IStableCoin(stableCoinAddress).allowedPairs(); for (uint256 i = 0; i < allowedPairs.length; i++) { IUniswapV2Pair pair = IUniswapV2Pair(allowedPairs[i]); if (pair.token0() == tokenAddress) { diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index b5b5642..e65c2bb 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -128,10 +128,11 @@ interface IStableCoin { ) external returns (uint256); /** - * Mint logic of the StableCoin. - * @dev Mint the $uSD token + * 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 * diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 5cc7394..16fcb62 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -248,6 +248,7 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin + * @dev Burn $usd to get back stablecoins from the pools */ function burn( uint256 pairIndex, @@ -257,6 +258,7 @@ contract StableCoin is ERC20, IStableCoin { ) public override _forAllowedPair(pairIndex) returns (uint256 removedA, uint256 removedB) { (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); + // Remove pooled stablecoins (removedA, removedB) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( tokenA, tokenB, @@ -266,6 +268,7 @@ contract StableCoin is ERC20, IStableCoin { msg.sender, block.timestamp + 1000 ); + // Actually burn the $uSD _burn( msg.sender, fromTokenToStable(tokenA, removedA) + fromTokenToStable(tokenB, removedB) @@ -402,8 +405,6 @@ contract StableCoin is ERC20, IStableCoin { * @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 From 881049fa348b9cf74fed68d353835c76ebfa4a32 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 1 Sep 2020 18:57:44 +0200 Subject: [PATCH 17/19] Fix docs --- .../farming/IUnifiedStableFarming.sol | 4 +- .../farming/UnifiedStableFarming.sol | 52 ++++++++----------- docs/build | 2 +- docs/mkdocs.yml | 2 + 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/contracts/stableCoin/farming/IUnifiedStableFarming.sol b/contracts/stableCoin/farming/IUnifiedStableFarming.sol index 29a1bcd..bff56ae 100644 --- a/contracts/stableCoin/farming/IUnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/IUnifiedStableFarming.sol @@ -64,12 +64,14 @@ interface IERC20 { } interface IUnifiedStableFarming { + function percentage() external view returns (uint256[] memory); + /** * @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 + * @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 diff --git a/contracts/stableCoin/farming/UnifiedStableFarming.sol b/contracts/stableCoin/farming/UnifiedStableFarming.sol index 20e9a76..0bb2ecd 100644 --- a/contracts/stableCoin/farming/UnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/UnifiedStableFarming.sol @@ -4,24 +4,23 @@ pragma solidity ^0.6.0; import "./IUnifiedStableFarming.sol"; -/** -* @inheritdoc IUnifiedStableFarming -*/ contract UnifiedStableFarming is IUnifiedStableFarming { address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; uint256[] private _percentage; - constructor(uint256[] memory percentage) { + constructor(uint256[] memory percentage) public { assert(percentage.length == 2); _percentage = percentage; } - function percentage() public override view returns(uint256[] memory) { + function percentage() public override view returns (uint256[] memory) { 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, @@ -48,8 +47,8 @@ contract UnifiedStableFarming is IUnifiedStableFarming { (uint256 returnA, uint256 returnB) = IStableCoin(stableCoinAddress).burn( pairIndex, pairAmount, - amountA, - amountB + amountAMin, + amountBMin ); (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); // Check that the pump was successful @@ -81,18 +80,13 @@ contract UnifiedStableFarming is IUnifiedStableFarming { uint256 stableCoinAmount ) private view returns (bool) { IStableCoin stableCoin = IStableCoin(stableCoinAddress); - uint256 cumulative = stableCoin.fromTokenToStable( - tokenAddress, - tokenValue - ); + uint256 cumulative = stableCoin.fromTokenToStable(tokenAddress, tokenValue); cumulative += stableCoin.fromTokenToStable(token0, return0); cumulative += stableCoin.fromTokenToStable(token1, return1); uint256 percentage = (cumulative * _percentage[0]) / _percentage[1]; uint256 cumulativePlus = cumulative + percentage; uint256 cumulativeMinus = cumulative - percentage; - return - stableCoinAmount >= cumulativeMinus && - stableCoinAmount <= cumulativePlus; + return stableCoinAmount >= cumulativeMinus && stableCoinAmount <= cumulativePlus; } /** @@ -124,29 +118,29 @@ contract UnifiedStableFarming is IUnifiedStableFarming { amountB ); // Mint $uSD - IStableCoin(stableCoinAddress).mint(pairIndex, amount0, amount1, amount0Min, amount1Min); + IStableCoin(stableCoinAddress).mint(pairIndex, 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 ); } // Send the tokens back to their owner - _flushToSender(token0, token1, stableCoinAddress); + _flushToSender(tokenA, tokenB, stableCoinAddress); } 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) @@ -200,13 +194,13 @@ contract UnifiedStableFarming is IUnifiedStableFarming { } function _flushToSender( - address token0, - address token1, - address token2 + address tokenA, + address tokenB, + address tokenC ) private { - _flushToSender(token0); - _flushToSender(token1); - _flushToSender(token2); + _flushToSender(tokenA); + _flushToSender(tokenB); + _flushToSender(tokenC); } /** diff --git a/docs/build b/docs/build index 4910af7..f49a677 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit 4910af7fdd9d8cbfd719c65ea83dba87dca26a95 +Subproject commit f49a677c1e5e1ef9bb6b4ca1ef65ff664d1710b5 diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 739f0a8..1eb8487 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -12,6 +12,8 @@ nav: - 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 From 671d244ac7c4da6bc42b9b501d3db2af3b95c76a Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sun, 6 Sep 2020 17:11:07 +0200 Subject: [PATCH 18/19] Update docs and project structure --- .../farming/IUnifiedStableFarming.sol | 74 +--- .../farming/UnifiedStableFarming.sol | 45 +-- contracts/stableCoin/microservices/IERC20.sol | 7 - .../stableCoin/microservices/IMVDProxy.sol | 3 +- .../stableCoin/microservices/IStateHolder.sol | 2 +- ...VotingTokensForStableCoinFunctionality.sol | 23 +- contracts/stableCoin/standalone/Address.sol | 162 -------- contracts/stableCoin/standalone/Context.sol | 24 -- contracts/stableCoin/standalone/ERC20.sol | 350 ------------------ contracts/stableCoin/standalone/IERC20.sol | 81 ---- .../standalone/IMVDFunctionalitiesManager.sol | 4 +- contracts/stableCoin/standalone/IMVDProxy.sol | 4 +- .../stableCoin/standalone/IStableCoin.sol | 7 +- .../stableCoin/standalone/IStateHolder.sol | 4 +- .../stableCoin/standalone/IUniswapV2Pair.sol | 32 -- .../standalone/IUniswapV2Router.sol | 101 ----- contracts/stableCoin/standalone/SafeMath.sol | 171 --------- .../stableCoin/standalone/StableCoin.sol | 17 +- package.json | 3 + yarn.lock | 28 ++ 20 files changed, 89 insertions(+), 1053 deletions(-) delete mode 100644 contracts/stableCoin/microservices/IERC20.sol delete mode 100644 contracts/stableCoin/standalone/Address.sol delete mode 100644 contracts/stableCoin/standalone/Context.sol delete mode 100644 contracts/stableCoin/standalone/ERC20.sol delete mode 100644 contracts/stableCoin/standalone/IERC20.sol delete mode 100644 contracts/stableCoin/standalone/IUniswapV2Pair.sol delete mode 100644 contracts/stableCoin/standalone/IUniswapV2Router.sol delete mode 100644 contracts/stableCoin/standalone/SafeMath.sol diff --git a/contracts/stableCoin/farming/IUnifiedStableFarming.sol b/contracts/stableCoin/farming/IUnifiedStableFarming.sol index 58cd6e1..710db11 100644 --- a/contracts/stableCoin/farming/IUnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/IUnifiedStableFarming.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.7.0; +pragma solidity >=0.7.0 <0.8.0; interface IUnifiedStableFarming { function percentage() external view returns (uint256[] memory); @@ -24,7 +24,7 @@ interface IUnifiedStableFarming { uint256 amountBMin, address tokenAddress, uint256 tokenValue - ) external; + ) external payable; /** * @dev Earn by dumping $uSD: Mint stablecoins obtaining $usd then swap it back for caller choice of @@ -51,73 +51,3 @@ interface IUnifiedStableFarming { uint256[] calldata stableCoinAmounts ) external; } - -interface IStableCoin { - function allowedPairs() external view returns (address[] memory); - - function fromTokenToStable(address tokenAddress, uint256 amount) - external - view - returns (uint256); - - function mint( - uint256 pairIndex, - uint256 amount0, - uint256 amount1, - uint256 amount0Min, - uint256 amount1Min - ) external returns (uint256); - - function burn( - uint256 pairIndex, - uint256 pairAmount, - uint256 amount0, - uint256 amount1 - ) external returns (uint256, uint256); -} - -interface IUniswapV2Pair { - function token0() external view returns (address); - - function token1() external view returns (address); -} - -interface IUniswapV2Router { - function WETH() external pure returns (address); - - 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); -} diff --git a/contracts/stableCoin/farming/UnifiedStableFarming.sol b/contracts/stableCoin/farming/UnifiedStableFarming.sol index 325d13a..66e92bc 100644 --- a/contracts/stableCoin/farming/UnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/UnifiedStableFarming.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0 <0.8.0; import "./IUnifiedStableFarming.sol"; +import "../standalone/IStableCoin.sol"; +import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; +import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; contract UnifiedStableFarming is IUnifiedStableFarming { address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; @@ -11,8 +14,8 @@ contract UnifiedStableFarming is IUnifiedStableFarming { uint256[] private _percentage; - constructor(uint256[] memory percentage) { - WETH_ADDRESS = IUniswapV2Router(UNISWAP_V2_ROUTER).WETH(); + constructor(uint256[] memory percentage) public { + WETH_ADDRESS = IUniswapV2Router02(UNISWAP_V2_ROUTER).WETH(); assert(percentage.length == 2); _percentage = percentage; } @@ -33,35 +36,18 @@ contract UnifiedStableFarming is IUnifiedStableFarming { 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 realTokenValue = tokenAddress == WETH_ADDRESS ? msg.value : tokenValue; + _swap(tokenAddress, stableCoinAddress, realTokenValue, address(this)); // Swap stablecoin for $uSD - (uint256 returnA, uint256 returnB) = IStableCoin(stableCoinAddress).burn( - pairIndex, - pairAmount, - amountAMin, - amountBMin - ); + IStableCoin(stableCoinAddress).burn(pairIndex, pairAmount, amountAMin, amountBMin); (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); // Send the tokens back to their owner - _flushToSender(tokenA, tokenB, stableCoinAddress); + _flushToSender(tokenA, tokenB, stableCoinAddress, address(0)); } - /** * @inheritdoc IUnifiedStableFarming */ @@ -170,13 +156,12 @@ contract UnifiedStableFarming is IUnifiedStableFarming { address tokenA, address tokenB, address tokenC, - address tokenD, + address tokenD ) private { _flushToSender(tokenA); _flushToSender(tokenB); _flushToSender(tokenC); _flushToSender(tokenD); - } /** @@ -186,7 +171,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { if (tokenAddress == address(0)) { return; } - if(tokenAddress == WETH_ADDRESS) { + if (tokenAddress == WETH_ADDRESS) { payable(msg.sender).transfer(address(this).balance); return; } @@ -212,7 +197,7 @@ 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; diff --git a/contracts/stableCoin/microservices/IERC20.sol b/contracts/stableCoin/microservices/IERC20.sol deleted file mode 100644 index ac0d35e..0000000 --- a/contracts/stableCoin/microservices/IERC20.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.6.0; - -interface IERC20 { - function mint(uint256 amount) external; - - function balanceOf(address account) external view returns (uint256); -} diff --git a/contracts/stableCoin/microservices/IMVDProxy.sol b/contracts/stableCoin/microservices/IMVDProxy.sol index a3021d5..917c2b2 100644 --- a/contracts/stableCoin/microservices/IMVDProxy.sol +++ b/contracts/stableCoin/microservices/IMVDProxy.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0 <0.8.0; interface IMVDProxy { function getToken() external view returns (address); diff --git a/contracts/stableCoin/microservices/IStateHolder.sol b/contracts/stableCoin/microservices/IStateHolder.sol index 2997b68..c2ade9c 100644 --- a/contracts/stableCoin/microservices/IStateHolder.sol +++ b/contracts/stableCoin/microservices/IStateHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0 <0.8.0; interface IStateHolder { function clear(string calldata varName) diff --git a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol index 24ae809..471d0a0 100644 --- a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,31 +1,38 @@ /* Discussion: * https://github.com/b-u-i-d-l/unifi */ + /* 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. + * 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: + * 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. + * 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. + * 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. + * 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.6.0; +pragma solidity >=0.7.0 <0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./IERC20.sol"; import "./IMVDFunctionalitiesManager.sol"; import "./IMVDProxy.sol"; import "./IStateHolder.sol"; /** * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) - * @dev This contract adds unifi minting capabilies to uSD + * @dev This contract adds unifi minting capabilities to uSD */ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { diff --git a/contracts/stableCoin/standalone/Address.sol b/contracts/stableCoin/standalone/Address.sol deleted file mode 100644 index 6b28275..0000000 --- a/contracts/stableCoin/standalone/Address.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain`call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return _functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return - functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - return _functionCallWithValue(target, data, value, errorMessage); - } - - function _functionCallWithValue( - address target, - bytes memory data, - uint256 weiValue, - string memory errorMessage - ) private returns (bytes memory) { - require(isContract(target), "Address: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.call{value: weiValue}(data); - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - // solhint-disable-next-line no-inline-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} diff --git a/contracts/stableCoin/standalone/Context.sol b/contracts/stableCoin/standalone/Context.sol deleted file mode 100644 index 97c73c4..0000000 --- a/contracts/stableCoin/standalone/Context.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with GSN meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal virtual view returns (address payable) { - return msg.sender; - } - - function _msgData() internal virtual view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol deleted file mode 100644 index 126be42..0000000 --- a/contracts/stableCoin/standalone/ERC20.sol +++ /dev/null @@ -1,350 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -import "./Context.sol"; -import "./IERC20.sol"; -import "./SafeMath.sol"; -import "./Address.sol"; -import "./IStableCoin.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. - * - * TIP: For a detailed writeup see our guide - * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * We have followed general OpenZeppelin guidelines: functions revert instead - * of returning `false` on failure. This behavior is nonetheless conventional - * and does not conflict with the expectations of ERC20 applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -abstract contract ERC20 is Context, IERC20 { - using SafeMath for uint256; - using Address for address; - - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - uint8 private _decimals; - - /** - * @dev Sets the values for {name} and {symbol}, initializes {decimals} with - * a default value of 18. - * - * To select a different value for {decimals}, use {_setupDecimals}. - * - * All three of these values are immutable: they can only be set once during - * construction. - */ - function init(string memory name, string memory symbol) internal { - require(keccak256(bytes(_symbol)) == keccak256(""), "Init already Called!"); - _name = name; - _symbol = symbol; - _decimals = 18; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5,05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is - * called. - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view returns (uint8) { - return _decimals; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public override view returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public override view returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `recipient` cannot be the zero address. - * - the caller must have a balance of at least `amount`. - */ - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(_msgSender(), recipient, amount); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) - public - virtual - override - view - returns (uint256) - { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(_msgSender(), spender, amount); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}; - * - * Requirements: - * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - * - the caller must have allowance for ``sender``'s tokens of at least - * `amount`. - */ - function transferFrom( - address sender, - address recipient, - uint256 amount - ) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - _approve( - sender, - _msgSender(), - _allowances[sender][_msgSender()].sub( - amount, - "ERC20: transfer amount exceeds allowance" - ) - ); - return true; - } - - /** - * @dev Atomically increases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); - return true; - } - - /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least - * `subtractedValue`. - */ - function decreaseAllowance(address spender, uint256 subtractedValue) - public - virtual - returns (bool) - { - _approve( - _msgSender(), - spender, - _allowances[_msgSender()][spender].sub( - subtractedValue, - "ERC20: decreased allowance below zero" - ) - ); - return true; - } - - /** - * @dev Moves tokens `amount` from `sender` to `recipient`. - * - * This is internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * Requirements: - * - * - `sender` cannot be the zero address. - * - `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - */ - function _transfer( - address sender, - address recipient, - uint256 amount - ) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); - _balances[recipient] = _balances[recipient].add(amount); - emit Transfer(sender, recipient, amount); - } - - /** - * @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * Requirements - * - * - `to` cannot be the zero address. - */ - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * Requirements - * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. - */ - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); - _totalSupply = _totalSupply.sub(amount); - emit Transfer(account, address(0), amount); - } - - /** - * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. - * - * This is internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - */ - function _approve( - address owner, - address spender, - uint256 amount - ) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - /** - * @dev Sets {decimals} to a value other than the default one of 18. - * - * WARNING: This function should only be called from the constructor. Most - * applications that interact with token contracts will not expect - * {decimals} to ever change, and may work incorrectly if it does. - */ - function _setupDecimals(uint8 decimals_) internal { - _decimals = decimals_; - } - - /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be to transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer( - address from, - address to, - uint256 amount - ) internal virtual {} -} diff --git a/contracts/stableCoin/standalone/IERC20.sol b/contracts/stableCoin/standalone/IERC20.sol deleted file mode 100644 index 82708eb..0000000 --- a/contracts/stableCoin/standalone/IERC20.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} diff --git a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol index a99e8f2..9cba846 100644 --- a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol +++ b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol @@ -1,4 +1,6 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.8.0; // DOCUMENT interface IMVDFunctionalitiesManager { diff --git a/contracts/stableCoin/standalone/IMVDProxy.sol b/contracts/stableCoin/standalone/IMVDProxy.sol index b4c6d23..be23c23 100644 --- a/contracts/stableCoin/standalone/IMVDProxy.sol +++ b/contracts/stableCoin/standalone/IMVDProxy.sol @@ -1,4 +1,6 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.8.0; // DOCUMENT interface IMVDProxy { diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index e65c2bb..53a53ef 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0 <0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title Interface for the $uSD aka unified Stable Dollar. @@ -11,7 +13,8 @@ pragma solidity ^0.6.0; * rebalancing schemes, $uSD is able reduce an holder exposure to a stable-coin failure. * */ -interface IStableCoin { + +interface IStableCoin is IERC20 { /** * Initialize the StableCoin. * @dev Constructor signature diff --git a/contracts/stableCoin/standalone/IStateHolder.sol b/contracts/stableCoin/standalone/IStateHolder.sol index 9a23fb8..6926edf 100644 --- a/contracts/stableCoin/standalone/IStateHolder.sol +++ b/contracts/stableCoin/standalone/IStateHolder.sol @@ -1,4 +1,6 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.8.0; // DOCUMENT interface IStateHolder { diff --git a/contracts/stableCoin/standalone/IUniswapV2Pair.sol b/contracts/stableCoin/standalone/IUniswapV2Pair.sol deleted file mode 100644 index 7658298..0000000 --- a/contracts/stableCoin/standalone/IUniswapV2Pair.sol +++ /dev/null @@ -1,32 +0,0 @@ -pragma solidity ^0.6.0; - -// DOCUMENT -/** - * @title Uniswap V2 Pair - */ -interface IUniswapV2Pair { - // DOCUMENT - function decimals() external pure returns (uint8); - - // DOCUMENT - function totalSupply() external view returns (uint256); - - // DOCUMENT - function token0() external view returns (address); - - // DOCUMENT - function token1() external view returns (address); - - // DOCUMENT - function balanceOf(address account) external view returns (uint256); - - // DOCUMENT - function getReserves() - external - view - returns ( - uint112 reserve0, - uint112 reserve1, - uint32 blockTimestampLast - ); -} diff --git a/contracts/stableCoin/standalone/IUniswapV2Router.sol b/contracts/stableCoin/standalone/IUniswapV2Router.sol deleted file mode 100644 index eb3849b..0000000 --- a/contracts/stableCoin/standalone/IUniswapV2Router.sol +++ /dev/null @@ -1,101 +0,0 @@ -pragma solidity ^0.6.0; - -/** - * @title Uniswap V2 Router - * @dev Route liquidity back and forth an Uniswap Liquidity Pool. - * For more information see: https://uniswap.org/docs/v2/smart-contracts/router02/ - * - */ -interface IUniswapV2Router { - /** - * https://uniswap.org/docs/v2/smart-contracts/library#getamountsout - * Given an input asset amount and an array of token addresses, calculates all subsequent maximum - * output token amounts by calling getReserves for each pair of token addresses in the path in - * turn, and using these to call getAmountOut. Useful for calculating optimal token amounts - * before calling swap. - */ - function getAmountsOut(uint256 amountIn, address[] calldata path) - external - view - returns (uint256[] memory amounts); - - /** - * @dev Removes liquidity from an ERC-20⇄ERC-20 pool - * - * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity - * - * ===== - * - * @param tokenA A pool token - * @param tokenB A pool token - * @param liquidity The amount of liquidity tokens to remove - * @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 to Recipient of the underlying assets - * @param deadline Unix timestamp after which the transaction will revert - * - * ===== - * - * @return amountA The amount of tokenA received - * @return amountB The amount of tokenB received - * - */ - function removeLiquidity( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external returns (uint256 amountA, uint256 amountB); - - /** - * @dev Add Liquidity to an ERC-20⇄ERC-20 pool - * - * - To cover all possible scenarios, msg.sender should have already given the router an allowance - * of at least amountADesired/amountBDesired on tokenA/tokenB. - * - Always adds assets at the ideal ratio, according to the price when the transaction is executed. - * - If a pool for the passed tokens does not exists, one is created automatically, and exactly - * amountADesired/amountBDesired tokens are added. - * - * https://uniswap.org/docs/v2/smart-contracts/router02/#addliquidity - * - * ===== - * - * @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. - * @param to Recipient of the underlying assets - * @param deadline Unix timestamp after which the transaction will revert - * - * ===== - * - * @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 addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) - external - returns ( - uint256 amountA, - uint256 amountB, - uint256 liquidity - ); -} diff --git a/contracts/stableCoin/standalone/SafeMath.sol b/contracts/stableCoin/standalone/SafeMath.sol deleted file mode 100644 index b2e90e8..0000000 --- a/contracts/stableCoin/standalone/SafeMath.sol +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index 16fcb62..bdd0fab 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0 <0.8.0; -import "./ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; +import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "./IStableCoin.sol"; import "./IMVDFunctionalitiesManager.sol"; import "./IMVDProxy.sol"; import "./IDoubleProxy.sol"; import "./IStateHolder.sol"; -import "./IUniswapV2Pair.sol"; -import "./IUniswapV2Router.sol"; /** * @title StableCoin @@ -188,7 +188,7 @@ contract StableCoin is ERC20, IStableCoin { 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 = IUniswapV2Router02(UNISWAP_V2_ROUTER).getAmountsOut(burnt, path)[1]; reward = (reward * _rebalanceRewardMultiplier[0]) / _rebalanceRewardMultiplier[1]; } @@ -259,7 +259,7 @@ contract StableCoin is ERC20, IStableCoin { (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); // Remove pooled stablecoins - (removedA, removedB) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( + (removedA, removedB) = IUniswapV2Router02(UNISWAP_V2_ROUTER).removeLiquidity( tokenA, tokenB, pairAmount, @@ -301,7 +301,8 @@ contract StableCoin is ERC20, IStableCoin { (uint256 credit, ) = differences(); (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); - (uint256 removed0, uint256 removed1) = IUniswapV2Router(UNISWAP_V2_ROUTER).removeLiquidity( + (uint256 removed0, uint256 removed1) = IUniswapV2Router02(UNISWAP_V2_ROUTER) + .removeLiquidity( tokenA, tokenB, pairAmount, @@ -425,7 +426,7 @@ contract StableCoin is ERC20, IStableCoin { uint256 liquidity ) { - (amountA, amountB, liquidity) = IUniswapV2Router(UNISWAP_V2_ROUTER).addLiquidity( + (amountA, amountB, liquidity) = IUniswapV2Router02(UNISWAP_V2_ROUTER).addLiquidity( tokenA, tokenB, amountADesired, diff --git a/package.json b/package.json index aa8b0b3..34042a0 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "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", diff --git a/yarn.lock b/yarn.lock index 4b6a045..86ba226 100644 --- a/yarn.lock +++ b/yarn.lock @@ -88,6 +88,11 @@ 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" @@ -98,6 +103,29 @@ 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" From 02d08afeb004c1caf339c5bfab459d1001a7d5e7 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Thu, 10 Sep 2020 21:45:53 +0200 Subject: [PATCH 19/19] Prepare for py-solidity-docgen integration --- .gitignore | 1 + CONTRIBUTING.md | 12 +- .../farming/IUnifiedStableFarming.sol | 74 ++++ .../farming/UnifiedStableFarming.sol | 27 +- .../IMVDFunctionalitiesManager.sol | 5 - .../stableCoin/microservices/IMVDProxy.sol | 22 - .../stableCoin/microservices/IStateHolder.sol | 13 - ...VotingTokensForStableCoinFunctionality.sol | 84 ++-- contracts/stableCoin/standalone/Address.sol | 141 +++++++ contracts/stableCoin/standalone/Context.sol | 24 ++ contracts/stableCoin/standalone/ERC20.sol | 376 ++++++++++++++++++ .../stableCoin/standalone/IDoubleProxy.sol | 6 - contracts/stableCoin/standalone/IERC20.sol | 77 ++++ .../standalone/IMVDFunctionalitiesManager.sol | 8 - contracts/stableCoin/standalone/IMVDProxy.sol | 19 - .../stableCoin/standalone/IStableCoin.sol | 100 ++++- .../stableCoin/standalone/IStateHolder.sol | 10 - contracts/stableCoin/standalone/SafeMath.sol | 159 ++++++++ .../stableCoin/standalone/StableCoin.sol | 95 +++-- docs/to_lowercase.sh | 3 - package.json | 2 +- 21 files changed, 1095 insertions(+), 163 deletions(-) delete mode 100644 contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol delete mode 100644 contracts/stableCoin/microservices/IMVDProxy.sol delete mode 100644 contracts/stableCoin/microservices/IStateHolder.sol create mode 100644 contracts/stableCoin/standalone/Address.sol create mode 100644 contracts/stableCoin/standalone/Context.sol create mode 100644 contracts/stableCoin/standalone/ERC20.sol delete mode 100644 contracts/stableCoin/standalone/IDoubleProxy.sol create mode 100644 contracts/stableCoin/standalone/IERC20.sol delete mode 100644 contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol delete mode 100644 contracts/stableCoin/standalone/IMVDProxy.sol delete mode 100644 contracts/stableCoin/standalone/IStateHolder.sol create mode 100644 contracts/stableCoin/standalone/SafeMath.sol delete mode 100755 docs/to_lowercase.sh diff --git a/.gitignore b/.gitignore index 3193fc0..da336f2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /**/spa/**/style.css 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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bfddaf5..d2292da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,11 +28,11 @@ 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] and [Solidity Domain for Sphinx]. +- Solidity portions of the code should be fully annotated using [NatSpec]. -Documentation is generated using [solidity-docgen] and rendered via [mkdocs]. -[solidity-docgen] parses NatSpec and outputs `.md` files inside `docs/md-build` according -to an Handlebars template located at `docs/solidity-docgen-templates/contract.hbs`. +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`. @@ -50,7 +50,7 @@ yarn docs:serve ### mkdocs -To install [mkdocs] Python must be installed in the system. +To install [mkdocs] and [py-solidity-docgen] Python must be installed in the system. ``` pip install docs/requirements.in @@ -63,5 +63,5 @@ pip install docs/requirements.in [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 -[solidity-docgen]: https://github.com/OpenZeppelin/solidity-docgen +[py-solidity-docgen]: https://github.com/b-u-i-d-l/py-solidity-docgen [mkdocs]: https://www.mkdocs.org/ diff --git a/contracts/stableCoin/farming/IUnifiedStableFarming.sol b/contracts/stableCoin/farming/IUnifiedStableFarming.sol index 710db11..617738f 100644 --- a/contracts/stableCoin/farming/IUnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/IUnifiedStableFarming.sol @@ -2,6 +2,10 @@ pragma solidity >=0.7.0 <0.8.0; +/** + * @title UnifiedStableFarming + * @dev Arbitrage helper + */ interface IUnifiedStableFarming { function percentage() external view returns (uint256[] memory); @@ -51,3 +55,73 @@ interface IUnifiedStableFarming { uint256[] calldata stableCoinAmounts ) external; } + +interface IStableCoin { + function allowedPairs() external view returns (address[] memory); + + function fromTokenToStable(address tokenAddress, uint256 amount) + external + view + returns (uint256); + + function mint( + uint256 pairIndex, + uint256 amount0, + uint256 amount1, + uint256 amount0Min, + uint256 amount1Min + ) external returns (uint256); + + function burn( + uint256 pairIndex, + uint256 pairAmount, + uint256 amount0, + uint256 amount1 + ) external returns (uint256, uint256); +} + +interface IUniswapV2Pair { + function token0() external view returns (address); + + function token1() external view returns (address); +} + +interface IUniswapV2Router02 { + function WETH() external pure returns (address); + + 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); +} diff --git a/contracts/stableCoin/farming/UnifiedStableFarming.sol b/contracts/stableCoin/farming/UnifiedStableFarming.sol index 66e92bc..5c005df 100644 --- a/contracts/stableCoin/farming/UnifiedStableFarming.sol +++ b/contracts/stableCoin/farming/UnifiedStableFarming.sol @@ -1,20 +1,18 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.8.0; +pragma solidity ^0.7.0; import "./IUnifiedStableFarming.sol"; -import "../standalone/IStableCoin.sol"; -import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; -import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; contract UnifiedStableFarming is IUnifiedStableFarming { - address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; + address + private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; address private WETH_ADDRESS; uint256[] private _percentage; - constructor(uint256[] memory percentage) public { + constructor(uint256[] memory percentage) { WETH_ADDRESS = IUniswapV2Router02(UNISWAP_V2_ROUTER).WETH(); assert(percentage.length == 2); _percentage = percentage; @@ -42,7 +40,12 @@ contract UnifiedStableFarming is IUnifiedStableFarming { 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); + IStableCoin(stableCoinAddress).burn( + pairIndex, + pairAmount, + amountAMin, + amountBMin + ); (address tokenA, address tokenB, ) = _getPairData(stableCoinAddress, pairIndex); // Send the tokens back to their owner _flushToSender(tokenA, tokenB, stableCoinAddress, address(0)); @@ -77,7 +80,13 @@ contract UnifiedStableFarming is IUnifiedStableFarming { amountB ); // Mint $uSD - IStableCoin(stableCoinAddress).mint(pairIndex, amountA, amountB, amountAMin, amountBMin); + IStableCoin(stableCoinAddress).mint( + pairIndex, + 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( @@ -204,7 +213,7 @@ contract UnifiedStableFarming is IUnifiedStableFarming { 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/microservices/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol deleted file mode 100644 index 72d2e2d..0000000 --- a/contracts/stableCoin/microservices/IMVDFunctionalitiesManager.sol +++ /dev/null @@ -1,5 +0,0 @@ -pragma solidity ^0.6.0; - -interface IMVDFunctionalitiesManager { - function isAuthorizedFunctionality(address functionality) external view returns (bool); -} diff --git a/contracts/stableCoin/microservices/IMVDProxy.sol b/contracts/stableCoin/microservices/IMVDProxy.sol deleted file mode 100644 index 917c2b2..0000000 --- a/contracts/stableCoin/microservices/IMVDProxy.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.8.0; - -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; -} diff --git a/contracts/stableCoin/microservices/IStateHolder.sol b/contracts/stableCoin/microservices/IStateHolder.sol deleted file mode 100644 index c2ade9c..0000000 --- a/contracts/stableCoin/microservices/IStateHolder.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.8.0; - -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 getBool(string calldata varName) external view returns (bool); -} diff --git a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol index 471d0a0..20504a0 100644 --- a/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/microservices/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,34 +1,19 @@ -/* 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. + * 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: + * 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. + * 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. + * 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. + * 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 <0.8.0; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import "./IMVDFunctionalitiesManager.sol"; -import "./IMVDProxy.sol"; -import "./IStateHolder.sol"; /** * @title Mint Voting Tokens ($unifi) by burning Stable Coin ($uSD) @@ -36,7 +21,9 @@ import "./IStateHolder.sol"; */ 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)), @@ -45,7 +32,9 @@ contract MintNewVotingTokensForStableCoinFunctionality { } 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)) @@ -105,8 +94,53 @@ contract MintNewVotingTokensForStableCoinFunctionality { 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 ? bytes1(uint8(bStr[i]) + 0x20) : bStr[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; +} + +interface IMVDFunctionalitiesManager { + 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 getBool(string calldata varName) external view returns (bool); +} + +interface IERC20 { + function mint(uint256 amount) external; + + function balanceOf(address account) external view returns (uint256); +} diff --git a/contracts/stableCoin/standalone/Address.sol b/contracts/stableCoin/standalone/Address.sol new file mode 100644 index 0000000..774e56c --- /dev/null +++ b/contracts/stableCoin/standalone/Address.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev Returns true if `account` is a contract. + * + * [IMPORTANT] + * ==== + * It is unsafe to assume that an address for which this function returns + * false is an externally-owned account (EOA) and not a contract. + * + * Among others, `isContract` will return false for the following + * types of addresses: + * + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies in extcodesize, which returns 0 for contracts in + // construction, since the code is only stored at the end of the + // constructor execution. + + uint256 size; + // solhint-disable-next-line no-inline-assembly + assembly { size := extcodesize(account) } + return size > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, "Address: insufficient balance"); + + // solhint-disable-next-line avoid-low-level-calls, avoid-call-value + (bool success, ) = recipient.call{ value: amount }(""); + require(success, "Address: unable to send value, recipient may have reverted"); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain`call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCall(target, data, "Address: low-level call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { + return _functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { + return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { + require(address(this).balance >= value, "Address: insufficient balance for call"); + return _functionCallWithValue(target, data, value, errorMessage); + } + + function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { + require(isContract(target), "Address: call to non-contract"); + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); + if (success) { + return returndata; + } else { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + + // solhint-disable-next-line no-inline-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } + } +} \ No newline at end of file diff --git a/contracts/stableCoin/standalone/Context.sol b/contracts/stableCoin/standalone/Context.sol new file mode 100644 index 0000000..df4d6e1 --- /dev/null +++ b/contracts/stableCoin/standalone/Context.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; + +/* + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with GSN meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address payable) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} \ No newline at end of file diff --git a/contracts/stableCoin/standalone/ERC20.sol b/contracts/stableCoin/standalone/ERC20.sol new file mode 100644 index 0000000..6d9fa02 --- /dev/null +++ b/contracts/stableCoin/standalone/ERC20.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; + +import "./Context.sol"; +import "./IERC20.sol"; +import "./SafeMath.sol"; +import "./Address.sol"; +import "./IStableCoin.sol"; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin guidelines: functions revert instead + * of returning `false` on failure. This behavior is nonetheless conventional + * and does not conflict with the expectations of ERC20 applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +abstract contract ERC20 is Context, IERC20 { + using SafeMath for uint256; + using Address for address; + + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + uint8 private _decimals; + + /** + * @dev Sets the values for {name} and {symbol}, initializes {decimals} with + * a default value of 18. + * + * To select a different value for {decimals}, use {_setupDecimals}. + * + * All three of these values are immutable: they can only be set once during + * construction. + */ + function init(string memory name, string memory symbol) internal { + require( + keccak256(bytes(_symbol)) == keccak256(""), + "Init already Called!" + ); + _name = name; + _symbol = symbol; + _decimals = 18; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5,05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is + * called. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view returns (uint8) { + return _decimals; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) + public + virtual + override + returns (bool) + { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) + public + virtual + override + view + returns (uint256) + { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) + public + virtual + override + returns (bool) + { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + _approve( + sender, + _msgSender(), + _allowances[sender][_msgSender()].sub( + amount, + "ERC20: transfer amount exceeds allowance" + ) + ); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) + public + virtual + returns (bool) + { + _approve( + _msgSender(), + spender, + _allowances[_msgSender()][spender].add(addedValue) + ); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) + public + virtual + returns (bool) + { + _approve( + _msgSender(), + spender, + _allowances[_msgSender()][spender].sub( + subtractedValue, + "ERC20: decreased allowance below zero" + ) + ); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub( + amount, + "ERC20: transfer amount exceeds balance" + ); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + _balances[account] = _balances[account].sub( + amount, + "ERC20: burn amount exceeds balance" + ); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Sets {decimals} to a value other than the default one of 18. + * + * WARNING: This function should only be called from the constructor. Most + * applications that interact with token contracts will not expect + * {decimals} to ever change, and may work incorrectly if it does. + */ + function _setupDecimals(uint8 decimals_) internal { + _decimals = decimals_; + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be to transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} +} \ No newline at end of file diff --git a/contracts/stableCoin/standalone/IDoubleProxy.sol b/contracts/stableCoin/standalone/IDoubleProxy.sol deleted file mode 100644 index 5b6c101..0000000 --- a/contracts/stableCoin/standalone/IDoubleProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.6.0; - -// DOCUMENT -interface IDoubleProxy { - function proxy() external view returns (address); -} diff --git a/contracts/stableCoin/standalone/IERC20.sol b/contracts/stableCoin/standalone/IERC20.sol new file mode 100644 index 0000000..c6eb6d3 --- /dev/null +++ b/contracts/stableCoin/standalone/IERC20.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} \ No newline at end of file diff --git a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol b/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol deleted file mode 100644 index 9cba846..0000000 --- a/contracts/stableCoin/standalone/IMVDFunctionalitiesManager.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.8.0; - -// DOCUMENT -interface IMVDFunctionalitiesManager { - function isAuthorizedFunctionality(address functionality) external view returns (bool); -} diff --git a/contracts/stableCoin/standalone/IMVDProxy.sol b/contracts/stableCoin/standalone/IMVDProxy.sol deleted file mode 100644 index be23c23..0000000 --- a/contracts/stableCoin/standalone/IMVDProxy.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.8.0; - -// DOCUMENT -interface IMVDProxy { - function getToken() external view returns (address); - - function getMVDFunctionalitiesManagerAddress() external view returns (address); - - function getMVDWalletAddress() external view returns (address); - - function getStateHolderAddress() external view returns (address); - - function submit(string calldata codeName, bytes calldata data) - external - payable - returns (bytes memory returnData); -} diff --git a/contracts/stableCoin/standalone/IStableCoin.sol b/contracts/stableCoin/standalone/IStableCoin.sol index 53a53ef..c14b4d8 100644 --- a/contracts/stableCoin/standalone/IStableCoin.sol +++ b/contracts/stableCoin/standalone/IStableCoin.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.8.0; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +pragma solidity ^0.7.0; +import "./IERC20.sol"; /** * @title Interface for the $uSD aka unified Stable Dollar. @@ -13,7 +12,6 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; * rebalancing schemes, $uSD is able reduce an holder exposure to a stable-coin failure. * */ - interface IStableCoin is IERC20 { /** * Initialize the StableCoin. @@ -120,7 +118,7 @@ interface IStableCoin is IERC20 { * @param amountBMin Bounds the extent to which the A/B price can go up before the transaction reverts. * Must be <= amountBDesired * - * @return Amount of freshly minted $uSD token + * @return minted Amount of freshly minted $uSD token */ function mint( uint256 pairIndex, @@ -128,7 +126,7 @@ interface IStableCoin is IERC20 { uint256 amountB, uint256 amountAMin, uint256 amountBMin - ) external returns (uint256); + ) external returns (uint256 minted); /** * Burn logic of the StableCoin. @@ -139,8 +137,8 @@ interface IStableCoin is IERC20 { * @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 amountA The amount of tokenA received - * @return amountB The amount of tokenB received + * @return removedA The amount of tokenA received + * @return removedB The amount of tokenB received * */ function burn( @@ -148,7 +146,7 @@ interface IStableCoin is IERC20 { uint256 pairAmount, uint256 amountAMin, uint256 amountBMin - ) external returns (uint256 amountA, uint256 amountB); + ) external returns (uint256 removedA, uint256 removedB); /** * @dev Rebalance by Credit is triggered when the total amount of source tokens' is greater @@ -174,3 +172,87 @@ interface IStableCoin is IERC20 { */ function rebalanceByDebt(uint256 amount) external returns (uint256); } + +interface IDoubleProxy { + function proxy() external view returns (address); +} + +interface IMVDProxy { + function getToken() external view returns (address); + + function getMVDFunctionalitiesManagerAddress() external view returns (address); + + function getMVDWalletAddress() external view returns (address); + + function getStateHolderAddress() external view returns (address); + + function submit(string calldata codeName, bytes calldata data) + external + payable + returns (bytes memory returnData); +} + +interface IMVDFunctionalitiesManager { + 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 IUniswapV2Router02 { + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + function removeLiquidity( + address tokenA, + address tokenB, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) external returns (uint256 amountA, uint256 amountB); + + function addLiquidity( + address tokenA, + address tokenB, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) + external + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ); +} + +interface IUniswapV2Pair { + function decimals() external pure returns (uint8); + + function totalSupply() external view returns (uint256); + + function token0() external view returns (address); + + function token1() external view returns (address); + + function balanceOf(address account) external view returns (uint256); + + function getReserves() + external + view + returns ( + uint112 reserve0, + uint112 reserve1, + uint32 blockTimestampLast + ); +} diff --git a/contracts/stableCoin/standalone/IStateHolder.sol b/contracts/stableCoin/standalone/IStateHolder.sol deleted file mode 100644 index 6926edf..0000000 --- a/contracts/stableCoin/standalone/IStateHolder.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.8.0; - -// DOCUMENT -interface IStateHolder { - function getBool(string calldata varName) external view returns (bool); - - function getUint256(string calldata varName) external view returns (uint256); -} diff --git a/contracts/stableCoin/standalone/SafeMath.sol b/contracts/stableCoin/standalone/SafeMath.sol new file mode 100644 index 0000000..4f9c084 --- /dev/null +++ b/contracts/stableCoin/standalone/SafeMath.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} \ No newline at end of file diff --git a/contracts/stableCoin/standalone/StableCoin.sol b/contracts/stableCoin/standalone/StableCoin.sol index bdd0fab..e787afc 100644 --- a/contracts/stableCoin/standalone/StableCoin.sol +++ b/contracts/stableCoin/standalone/StableCoin.sol @@ -1,15 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.8.0; +pragma solidity ^0.7.0; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; -import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; +import "./ERC20.sol"; import "./IStableCoin.sol"; -import "./IMVDFunctionalitiesManager.sol"; -import "./IMVDProxy.sol"; -import "./IDoubleProxy.sol"; -import "./IStateHolder.sol"; /** * @title StableCoin @@ -21,7 +15,8 @@ contract StableCoin is ERC20, IStableCoin { // | ----- ATTRIBUTES ----- | // |------------------------------------------------------------------------------------------| - address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; + address + private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; address private _doubleProxy; @@ -50,7 +45,7 @@ contract StableCoin is ERC20, IStableCoin { uint256[] memory rebalanceRewardMultiplier, uint256[] memory timeWindows, uint256[] memory mintables - ) public { + ) { if (doubleProxy == address(0)) { return; } @@ -103,8 +98,13 @@ contract StableCoin is ERC20, IStableCoin { * @inheritdoc IStableCoin */ function availableToMint() public override view returns (uint256) { - uint256 mintable = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - if (_timeWindows.length > 0 && block.number < _timeWindows[_timeWindows.length - 1]) { + + uint256 mintable + = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + 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]; @@ -147,7 +147,12 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin */ - function tierData() public override view returns (uint256[] memory, uint256[] memory) { + function tierData() + public + override + view + returns (uint256[] memory, uint256[] memory) + { return (_timeWindows, _mintables); } @@ -158,7 +163,11 @@ contract StableCoin is ERC20, IStableCoin { /** * @inheritdoc IStableCoin */ - function setAllowedPairs(address[] memory newAllowedPairs) public override _byCommunity { + function setAllowedPairs(address[] memory newAllowedPairs) + public + override + _byCommunity + { _allowedPairs = newAllowedPairs; } @@ -226,8 +235,12 @@ contract StableCoin is ERC20, IStableCoin { ) public override _forAllowedPair(pairIndex) returns (uint256 minted) { // NOTE: Use DFO protocol to check for authorization require( - IStateHolder(IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress()) - .getBool(_toStateHolderKey("stablecoin.authorized", _toString(address(this)))), + IStateHolder( + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress() + ) + .getBool( + _toStateHolderKey("stablecoin.authorized", _toString(address(this))) + ), "Unauthorized action!" ); (address tokenA, address tokenB, ) = _getPairData(pairIndex); @@ -241,8 +254,13 @@ contract StableCoin is ERC20, IStableCoin { amountAMin, amountBMin ); - minted = fromTokenToStable(tokenA, firstAmount) + fromTokenToStable(tokenB, secondAmount); - require(minted <= availableToMint(), "Minting amount is greater than availability!"); + minted = + fromTokenToStable(tokenA, firstAmount) + + fromTokenToStable(tokenB, secondAmount); + require( + minted <= availableToMint(), + "Minting amount is greater than availability!" + ); _mint(msg.sender, minted); } @@ -255,7 +273,12 @@ contract StableCoin is ERC20, IStableCoin { uint256 pairAmount, uint256 amountAMin, uint256 amountBMin - ) public override _forAllowedPair(pairIndex) returns (uint256 removedA, uint256 removedB) { + ) + public + override + _forAllowedPair(pairIndex) + returns (uint256 removedA, uint256 removedB) + { (address tokenA, address tokenB, address pairAddress) = _getPairData(pairIndex); _checkAllowance(pairAddress, pairAmount); // Remove pooled stablecoins @@ -292,7 +315,8 @@ contract StableCoin is ERC20, IStableCoin { block.number >= _lastRedeemBlock + IStateHolder( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getStateHolderAddress() + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) + .getStateHolderAddress() ) .getUint256("stablecoin.rebalancebycredit.block.interval"), "Unauthorized action!" @@ -311,7 +335,9 @@ contract StableCoin is ERC20, IStableCoin { IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDWalletAddress(), block.timestamp + 1000 ); - redeemed = fromTokenToStable(tokenA, removed0) + fromTokenToStable(tokenB, removed1); + redeemed = + fromTokenToStable(tokenA, removed0) + + fromTokenToStable(tokenB, removed1); require(redeemed <= credit, "Cannot redeem given pair amount"); } @@ -325,7 +351,12 @@ contract StableCoin is ERC20, IStableCoin { _burn(msg.sender, amount); IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).submit( "mintNewVotingTokensForStableCoin", - abi.encode(address(0), 0, reward = calculateRebalanceByDebtReward(amount), msg.sender) + abi.encode( + address(0), + 0, + reward = calculateRebalanceByDebtReward(amount), + msg.sender + ) ); } @@ -337,7 +368,8 @@ contract StableCoin is ERC20, IStableCoin { modifier _byCommunity() { require( IMVDFunctionalitiesManager( - IMVDProxy(IDoubleProxy(_doubleProxy).proxy()).getMVDFunctionalitiesManagerAddress() + IMVDProxy(IDoubleProxy(_doubleProxy).proxy()) + .getMVDFunctionalitiesManagerAddress() ) .isAuthorizedFunctionality(msg.sender), "Unauthorized Action!" @@ -375,7 +407,9 @@ contract StableCoin is ERC20, IStableCoin { /** * // DOCUMENT */ - function _transferTokensAndCheckAllowance(address tokenAddress, uint256 value) private { + function _transferTokensAndCheckAllowance(address tokenAddress, uint256 value) + private + { IERC20(tokenAddress).transferFrom(msg.sender, address(this), value); _checkAllowance(tokenAddress, value); } @@ -426,7 +460,8 @@ contract StableCoin is ERC20, IStableCoin { uint256 liquidity ) { - (amountA, amountB, liquidity) = IUniswapV2Router02(UNISWAP_V2_ROUTER).addLiquidity( + (amountA, amountB, liquidity) = IUniswapV2Router02(UNISWAP_V2_ROUTER) + .addLiquidity( tokenA, tokenB, amountADesired, @@ -447,7 +482,11 @@ contract StableCoin is ERC20, IStableCoin { /** * // DOCUMENT */ - function _getPairAmount(uint256 i) private view returns (uint256 amount0, uint256 amount1) { + function _getPairAmount(uint256 i) + private + view + returns (uint256 amount0, uint256 amount1) + { (address token0, address token1, address pairAddress) = _getPairData(i); IUniswapV2Pair pair = IUniswapV2Pair(pairAddress); uint256 pairAmount = pair.balanceOf(address(this)); @@ -491,7 +530,9 @@ contract StableCoin is ERC20, IStableCoin { 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 ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i]; + bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A + ? bytes1(uint8(bStr[i]) + 0x20) + : bStr[i]; } return string(bStr); } diff --git a/docs/to_lowercase.sh b/docs/to_lowercase.sh deleted file mode 100755 index 80ec06f..0000000 --- a/docs/to_lowercase.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/bash - -sed -i -E 's/(\(#.*)/\L\1\E/g' md-build/stableCoin/**/*.md diff --git a/package.json b/package.json index 34042a0..038d2a9 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "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 && solidity-docgen -i ../contracts -o md-build -t solidity-docgen-templates && cp ../*.md md-build && ./to_lowercase.sh", + "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" }