From bce54aba135442833c8121125907e8ed0e56d716 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Sun, 28 Jun 2020 23:15:51 +1000 Subject: [PATCH 01/16] fix formating on connectors/curve.sol; adding @openzeppelin/test-helpers, ganache-cli; fixing test/CurveProtocol.js to pass; added truffle network for tenderly proxy; added .nvmrc to set to node v12 as ganache-cli requires; --- .nvmrc | 1 + contracts/connectors/curve.sol | 365 ++++--- package-lock.json | 1669 ++++++++++++++++++++++++++++++-- package.json | 7 +- test/CurveProtocol.js | 167 ++-- truffle-config.js | 8 +- 6 files changed, 1897 insertions(+), 320 deletions(-) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..46a8184 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v12.18.1 diff --git a/contracts/connectors/curve.sol b/contracts/connectors/curve.sol index 0e0efb9..3dbd2a4 100644 --- a/contracts/connectors/curve.sol +++ b/contracts/connectors/curve.sol @@ -6,224 +6,223 @@ import { Stores } from "../common/stores.sol"; import { DSMath } from "../common/math.sol"; interface ICurve { - function underlying_coins(int128 tokenId) external view returns (address token); - function calc_token_amount(uint256[4] calldata amounts, bool deposit) external returns (uint256 amount); - function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external; - function get_dy(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt) external returns (uint256 buyTokenAmt); - function exchange(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt, uint256 minBuyToken) external; - function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external; + function underlying_coins(int128 tokenId) external view returns (address token); + function calc_token_amount(uint256[4] calldata amounts, bool deposit) external returns (uint256 amount); + function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external; + function get_dy(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt) external returns (uint256 buyTokenAmt); + function exchange(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt, uint256 minBuyToken) external; + function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external; } interface ICurveZap { - function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external returns (uint256 amount); + function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external returns (uint256 amount); } contract CurveHelpers is Stores, DSMath { - /** - * @dev Return Curve Swap Address - */ - function getCurveSwapAddr() internal pure returns (address) { - return 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD; - } + /** + * @dev Return Curve Swap Address + */ + function getCurveSwapAddr() internal pure returns (address) { + return 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD; + } - /** - * @dev Return Curve Token Address - */ - function getCurveTokenAddr() internal pure returns (address) { - return 0xC25a3A3b969415c80451098fa907EC722572917F; - } + /** + * @dev Return Curve Token Address + */ + function getCurveTokenAddr() internal pure returns (address) { + return 0xC25a3A3b969415c80451098fa907EC722572917F; + } - /** - * @dev Return Curve Zap Address - */ - function getCurveZapAddr() internal pure returns (address) { - return 0xFCBa3E75865d2d561BE8D220616520c171F12851; - } + /** + * @dev Return Curve Zap Address + */ + function getCurveZapAddr() internal pure returns (address) { + return 0xFCBa3E75865d2d561BE8D220616520c171F12851; + } - function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { - amt = (_amt / 10 ** (18 - _dec)); - } + function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = (_amt / 10 ** (18 - _dec)); + } - function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { - amt = mul(_amt, 10 ** (18 - _dec)); - } + function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = mul(_amt, 10 ** (18 - _dec)); + } - function getTokenI(address token) internal pure returns (int128 i) { - if (token == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { - // DAI Token - i = 0; - } else if (token == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) { - // USDC Token - i = 1; - } else if (token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)) { - // USDT Token - i = 2; - } else if (token == address(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) { - // sUSD Token - i = 3; - } else { - revert("token-not-found."); - } + function getTokenI(address token) internal pure returns (int128 i) { + if (token == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { + // DAI Token + i = 0; + } else if (token == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) { + // USDC Token + i = 1; + } else if (token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)) { + // USDT Token + i = 2; + } else if (token == address(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) { + // sUSD Token + i = 3; + } else { + revert("token-not-found."); } + } - function getTokenAddr(ICurve curve, uint256 i) internal view returns (address token) { - token = curve.underlying_coins(int128(i)); - require(token != address(0), "token-not-found."); - } + function getTokenAddr(ICurve curve, uint256 i) internal view returns (address token) { + token = curve.underlying_coins(int128(i)); + require(token != address(0), "token-not-found."); + } } - contract CurveProtocol is CurveHelpers { - event LogSell( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - event LogDeposit(address token, uint256 amt, uint256 mintAmt, uint256 getId, uint256 setId); - event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId, uint256 setId); + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + event LogDeposit(address token, uint256 amt, uint256 mintAmt, uint256 getId, uint256 setId); + event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId, uint256 setId); - /** - * @dev Sell Stable ERC20_Token. - * @param buyAddr buying token address. - * @param sellAddr selling token amount. - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. + /** + * @dev Sell Stable ERC20_Token. + * @param buyAddr buying token address. + * @param sellAddr selling token amount. + * @param sellAmt selling token amount. + * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. */ - function sell( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - uint getId, - uint setId - ) external payable { - uint _sellAmt = getUint(getId, sellAmt); - ICurve curve = ICurve(getCurveSwapAddr()); - TokenInterface _buyToken = TokenInterface(buyAddr); - TokenInterface _sellToken = TokenInterface(sellAddr); - _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt; - _sellToken.approve(address(curve), _sellAmt); + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint getId, + uint setId + ) external payable { + uint _sellAmt = getUint(getId, sellAmt); + ICurve curve = ICurve(getCurveSwapAddr()); + TokenInterface _buyToken = TokenInterface(buyAddr); + TokenInterface _sellToken = TokenInterface(sellAddr); + _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt; + _sellToken.approve(address(curve), _sellAmt); - uint _slippageAmt = convert18ToDec(_buyToken.decimals(), wmul(unitAmt, convertTo18(_sellToken.decimals(), _sellAmt))); + uint _slippageAmt = convert18ToDec(_buyToken.decimals(), wmul(unitAmt, convertTo18(_sellToken.decimals(), _sellAmt))); - uint intialBal = _buyToken.balanceOf(address(this)); - curve.exchange(getTokenI(sellAddr), getTokenI(buyAddr), _sellAmt, _slippageAmt); - uint finalBal = _buyToken.balanceOf(address(this)); + uint intialBal = _buyToken.balanceOf(address(this)); + curve.exchange(getTokenI(sellAddr), getTokenI(buyAddr), _sellAmt, _slippageAmt); + uint finalBal = _buyToken.balanceOf(address(this)); - uint _buyAmt = sub(finalBal, intialBal); + uint _buyAmt = sub(finalBal, intialBal); - setUint(setId, _buyAmt); + setUint(setId, _buyAmt); - emit LogSell(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); - bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); - bytes memory _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); - emitEvent(_eventCode, _eventParam); + emit LogSell(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } + + /** + * @dev Deposit Token. + * @param token token address. + * @param amt token amount. + * @param unitAmt unit amount of curve_amt/token_amt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function deposit( + address token, + uint amt, + uint unitAmt, + uint getId, + uint setId + ) external payable { + uint256 _amt = getUint(getId, amt); + TokenInterface tokenContract = TokenInterface(token); + + _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; + uint[4] memory _amts; + _amts[uint(getTokenI(token))] = _amt; + + tokenContract.approve(getCurveSwapAddr(), _amt); + + uint _amt18 = convertTo18(tokenContract.decimals(), _amt); + uint _slippageAmt = wmul(unitAmt, _amt18); + + TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); + uint initialCurveBal = curveTokenContract.balanceOf(address(this)); + + ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt); + + uint finalCurveBal = curveTokenContract.balanceOf(address(this)); + + uint mintAmt = sub(finalCurveBal, initialCurveBal); + + setUint(setId, mintAmt); + + emit LogDeposit(token, _amt, mintAmt, getId, setId); + bytes32 _eventCode = keccak256("LogDeposit(address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(token, _amt, mintAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } + + /** + * @dev Withdraw Token. + * @param token token address. + * @param amt token amount. + * @param unitAmt unit amount of curve_amt/token_amt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function withdraw( + address token, + uint256 amt, + uint256 unitAmt, + uint getId, + uint setId + ) external payable { + uint _amt = getUint(getId, amt); + int128 tokenId = getTokenI(token); + + TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); + ICurveZap curveZap = ICurveZap(getCurveZapAddr()); + ICurve curveSwap = ICurve(getCurveSwapAddr()); + + uint _curveAmt; + uint[4] memory _amts; + if (_amt == uint(-1)) { + _curveAmt = curveTokenContract.balanceOf(address(this)); + _amt = curveZap.calc_withdraw_one_coin(_curveAmt, tokenId); + _amts[uint(tokenId)] = _amt; + } else { + _amts[uint(tokenId)] = _amt; + _curveAmt = curveSwap.calc_token_amount(_amts, false); } - /** - * @dev Deposit Token. - * @param token token address. - * @param amt token amount. - * @param unitAmt unit amount of curve_amt/token_amt with slippage. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function deposit( - address token, - uint amt, - uint unitAmt, - uint getId, - uint setId - ) external payable { - uint256 _amt = getUint(getId, amt); - TokenInterface tokenContract = TokenInterface(token); - _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; - uint[4] memory _amts; - _amts[uint(getTokenI(token))] = _amt; + uint _amt18 = convertTo18(TokenInterface(token).decimals(), _amt); + uint _slippageAmt = wmul(unitAmt, _amt18); - tokenContract.approve(getCurveSwapAddr(), _amt); + curveTokenContract.approve(address(curveSwap), 0); + curveTokenContract.approve(address(curveSwap), _slippageAmt); - uint _amt18 = convertTo18(tokenContract.decimals(), _amt); - uint _slippageAmt = wmul(unitAmt, _amt18); + curveSwap.remove_liquidity_imbalance(_amts, _slippageAmt); - TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); - uint initialCurveBal = curveTokenContract.balanceOf(address(this)); + setUint(setId, _amt); - ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt); - - uint finalCurveBal = curveTokenContract.balanceOf(address(this)); - - uint mintAmt = sub(finalCurveBal, initialCurveBal); - - setUint(setId, mintAmt); - - emit LogDeposit(token, _amt, mintAmt, getId, setId); - bytes32 _eventCode = keccak256("LogDeposit(address,uint256,uint256,uint256,uint256)"); - bytes memory _eventParam = abi.encode(token, _amt, mintAmt, getId, setId); - emitEvent(_eventCode, _eventParam); - } - - /** - * @dev Withdraw Token. - * @param token token address. - * @param amt token amount. - * @param unitAmt unit amount of curve_amt/token_amt with slippage. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function withdraw( - address token, - uint256 amt, - uint256 unitAmt, - uint getId, - uint setId - ) external payable { - uint _amt = getUint(getId, amt); - int128 tokenId = getTokenI(token); - - TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); - ICurveZap curveZap = ICurveZap(getCurveZapAddr()); - ICurve curveSwap = ICurve(getCurveSwapAddr()); - - uint _curveAmt; - uint[4] memory _amts; - if (_amt == uint(-1)) { - _curveAmt = curveTokenContract.balanceOf(address(this)); - _amt = curveZap.calc_withdraw_one_coin(_curveAmt, tokenId); - _amts[uint(tokenId)] = _amt; - } else { - _amts[uint(tokenId)] = _amt; - _curveAmt = curveSwap.calc_token_amount(_amts, false); - } - - - uint _amt18 = convertTo18(TokenInterface(token).decimals(), _amt); - uint _slippageAmt = wmul(unitAmt, _amt18); - - curveTokenContract.approve(address(curveSwap), 0); - curveTokenContract.approve(address(curveSwap), _slippageAmt); - - curveSwap.remove_liquidity_imbalance(_amts, _slippageAmt); - - setUint(setId, _amt); - - emit LogWithdraw(token, _amt, _curveAmt, getId, setId); - bytes32 _eventCode = keccak256("LogWithdraw(address,uint256,uint256,uint256,uint256)"); - bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId); - emitEvent(_eventCode, _eventParam); - } + emit LogWithdraw(token, _amt, _curveAmt, getId, setId); + bytes32 _eventCode = keccak256("LogWithdraw(address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } } contract ConnectCurve is CurveProtocol { - string public name = "Curve-susd-v1.2"; + string public name = "Curve-susd-v1.2"; } diff --git a/package-lock.json b/package-lock.json index 5d8def2..bc00856 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,663 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@openzeppelin/contract-loader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contract-loader/-/contract-loader-0.4.0.tgz", + "integrity": "sha512-K+Pl4tn0FbxMSP0H9sgi61ayCbecpqhQmuBshelC7A3q2MlpcqWRJan0xijpwdtv6TORNd5oZNe/+f3l+GD6tw==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "try-require": "^1.2.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "@openzeppelin/contracts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.1.0.tgz", + "integrity": "sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ==" + }, + "@openzeppelin/test-helpers": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/test-helpers/-/test-helpers-0.5.6.tgz", + "integrity": "sha512-8U4sR4ed4cFmc6UKj7akUxZzQJKU9P3p/3RbF+urQuRLLhBaB8zSya1m9VB7/anYEZnBmTDk8LuVgAmYaCPs9A==", + "dev": true, + "requires": { + "@openzeppelin/contract-loader": "^0.4.0", + "@truffle/contract": "^4.0.35 <4.2.2", + "ansi-colors": "^3.2.3", + "chai": "^4.2.0", + "chai-bn": "^0.2.1", + "ethjs-abi": "^0.2.1", + "lodash.flatten": "^4.4.0", + "semver": "^5.6.0", + "web3": "^1.2.1", + "web3-utils": "^1.2.1" + } + }, + "@openzeppelin/upgrades": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades/-/upgrades-2.8.0.tgz", + "integrity": "sha512-LzjTQPeljPsgHDPdZyH9cMCbIHZILgd2cpNcYEkdsC2IylBYRHShlbEDXJV9snnqg9JWfzPiKIqyj3XVliwtqQ==", + "requires": { + "@types/cbor": "^2.0.0", + "axios": "^0.18.0", + "bignumber.js": "^7.2.0", + "cbor": "^4.1.5", + "chalk": "^2.4.1", + "ethers": "^4.0.20", + "glob": "^7.1.3", + "lodash": "^4.17.15", + "semver": "^5.5.1", + "spinnies": "^0.4.2", + "truffle-flattener": "^1.4.0", + "web3": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" + }, + "dependencies": { + "@types/node": { + "version": "12.12.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.47.tgz", + "integrity": "sha512-yzBInQFhdY8kaZmqoL2+3U5dSTMrKaYcb561VU+lDzAYvqt+2lojvBEy+hmpSNuXnPTx7m9+04CzWYOUqWME2A==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "ethers": { + "version": "4.0.47", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.47.tgz", + "integrity": "sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ==", + "requires": { + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.5.2", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + }, + "web3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", + "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", + "requires": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.2", + "web3-core": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-shh": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-bzz": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", + "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "requires": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "dependencies": { + "@types/node": { + "version": "10.17.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz", + "integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==" + } + } + }, + "web3-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", + "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "requires": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-requestmanager": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", + "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "requires": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-method": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", + "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-promievent": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", + "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + } + }, + "web3-core-requestmanager": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", + "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-providers-http": "1.2.2", + "web3-providers-ipc": "1.2.2", + "web3-providers-ws": "1.2.2" + } + }, + "web3-core-subscriptions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", + "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "requires": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + } + }, + "web3-eth": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", + "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "requires": { + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-accounts": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-eth-ens": "1.2.2", + "web3-eth-iban": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-abi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", + "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "requires": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.2" + }, + "dependencies": { + "@types/node": { + "version": "10.17.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz", + "integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==" + }, + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" + } + } + }, + "web3-eth-accounts": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", + "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-shim": "github:web3-js/scrypt-shim", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "web3-eth-contract": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", + "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "requires": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-ens": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", + "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "requires": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-iban": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", + "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "requires": { + "bn.js": "4.11.8", + "web3-utils": "1.2.2" + } + }, + "web3-eth-personal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", + "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "requires": { + "@types/node": "^12.6.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-net": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", + "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "requires": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-providers-http": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", + "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "requires": { + "web3-core-helpers": "1.2.2", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", + "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "requires": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + } + }, + "web3-providers-ws": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", + "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + } + }, + "web3-shh": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", + "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "requires": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-net": "1.2.2" + } + }, + "web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "requires": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + } + }, + "websocket": { + "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", + "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", + "requires": { + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + } + } + } + }, + "@resolver-engine/core": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.2.1.tgz", + "integrity": "sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A==", + "requires": { + "debug": "^3.1.0", + "request": "^2.85.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@resolver-engine/fs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.2.1.tgz", + "integrity": "sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg==", + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@resolver-engine/imports": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.2.2.tgz", + "integrity": "sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg==", + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@resolver-engine/imports-fs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz", + "integrity": "sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ==", + "requires": { + "@resolver-engine/fs": "^0.2.1", + "@resolver-engine/imports": "^0.2.2", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" }, + "@solidity-parser/parser": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.6.2.tgz", + "integrity": "sha512-kUVUvrqttndeprLoXjI5arWHeiP3uh4XODAKbG+ZaWHCVQeelxCbnXBeWxZ2BPHdXgH0xR9dU1b916JhDhbgAA==" + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -33,14 +685,16 @@ "version": "0.0.18", "resolved": "https://registry.npmjs.org/@truffle/blockchain-utils/-/blockchain-utils-0.0.18.tgz", "integrity": "sha512-XnRu5p1QO9krJizOeBY5WfzPDvEOmCnOT5u6qF8uN3Kkq9vcH3ZqW4XTuzz9ERZNpZfWb3UJx4PUosgeHLs5vw==", + "dev": true, "requires": { "source-map-support": "^0.5.16" } }, "@truffle/contract": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.2.3.tgz", - "integrity": "sha512-nC6BNvUTDWt1zceDQkrIodaYgwN5UIau5tMfSM4FuOYMAHKxytN7s9fC6vLzyTFzFHohyQ0fEmsCEbRNDGjhAQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.2.1.tgz", + "integrity": "sha512-af1rUyU/W75GYHt/i7r+NwHozwaCma7V/q/+SRZ3Cw2MFaGOQ0dA/ZGhH8P1F0fmDiUe1DBEIbKxXWai0PWFYg==", + "dev": true, "requires": { "@truffle/blockchain-utils": "^0.0.18", "@truffle/contract-schema": "^3.1.0", @@ -52,7 +706,6 @@ "exorcist": "^1.0.1", "source-map-support": "^0.5.16", "web3": "1.2.1", - "web3-core-helpers": "1.2.1", "web3-core-promievent": "1.2.1", "web3-eth-abi": "1.2.1", "web3-utils": "1.2.1" @@ -61,7 +714,8 @@ "bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", - "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==", + "dev": true } } }, @@ -78,16 +732,18 @@ "@truffle/error": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.8.tgz", - "integrity": "sha512-x55rtRuNfRO1azmZ30iR0pf0OJ6flQqbax1hJz+Avk1K5fdmOv5cr22s9qFnwTWnS6Bw0jvJEoR0ITsM7cPKtQ==" + "integrity": "sha512-x55rtRuNfRO1azmZ30iR0pf0OJ6flQqbax1hJz+Avk1K5fdmOv5cr22s9qFnwTWnS6Bw0jvJEoR0ITsM7cPKtQ==", + "dev": true }, "@truffle/interface-adapter": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.6.tgz", - "integrity": "sha512-FZAUb7tx/7VbxpAbo70+K2v22j1O7y4BwhWypRwYpf1YbE2C1OCo/L8zInaW5LfzRd2BEsfb2GjUgbK9VaFrDA==", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.9.tgz", + "integrity": "sha512-2dYccf7lAwx90NVYmn89QABpd3dx7BxvDAaHgzVa2YVOUkTUpkZiaIsD2YlsVQ1rew17wMNi5WXH2RFnmzQ82A==", + "dev": true, "requires": { "bn.js": "^4.11.8", "ethers": "^4.0.32", - "source-map-support": "^0.5.16", + "source-map-support": "^0.5.19", "web3": "1.2.1" }, "dependencies": { @@ -95,6 +751,7 @@ "version": "4.0.47", "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.47.tgz", "integrity": "sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ==", + "dev": true, "requires": { "aes-js": "3.0.0", "bn.js": "^4.4.0", @@ -111,6 +768,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.0" @@ -119,22 +777,26 @@ "js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true }, "scrypt-js": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true }, "setimmediate": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true }, "uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true } } }, @@ -146,6 +808,14 @@ "@types/node": "*" } }, + "@types/cbor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/cbor/-/cbor-2.0.0.tgz", + "integrity": "sha1-xievwu4i8j8jN/7LNGKKT5fGr7s=", + "requires": { + "@types/node": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -197,7 +867,8 @@ "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true }, "ansi-regex": { "version": "2.1.1", @@ -774,10 +1445,29 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "cbor": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-4.3.0.tgz", + "integrity": "sha512-CvzaxQlaJVa88sdtTWvLJ++MbdtPHtZOBBNjm7h3YKUHILMs9nQyD4AC6hvFZy7GBVB3I6bRibJcxeHydyT2IQ==", + "requires": { + "bignumber.js": "^9.0.0", + "commander": "^3.0.0", + "json-text-sequence": "^0.1", + "nofilter": "^1.0.3" + }, + "dependencies": { + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + } + } + }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -790,7 +1480,8 @@ "chai-bn": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.1.tgz", - "integrity": "sha512-01jt2gSXAw7UYFPT5K8d7HYjdXj2vyeIuE+0T/34FWzlNcVbs1JkPxRu7rYMfQnJhrHT8Nr6qjSf5ZwwLU2EYg==" + "integrity": "sha512-01jt2gSXAw7UYFPT5K8d7HYjdXj2vyeIuE+0T/34FWzlNcVbs1JkPxRu7rYMfQnJhrHT8Nr6qjSf5ZwwLU2EYg==", + "dev": true }, "chalk": { "version": "4.0.0", @@ -804,7 +1495,8 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true }, "chokidar": { "version": "1.7.0", @@ -884,6 +1576,14 @@ "timers-ext": "^0.1.5" } }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, "cli-logger": { "version": "0.5.40", "resolved": "https://registry.npmjs.org/cli-logger/-/cli-logger-0.5.40.tgz", @@ -1019,6 +1719,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" }, @@ -1026,7 +1727,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -1268,6 +1970,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -1346,6 +2049,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1510,8 +2218,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.8.1", @@ -1590,10 +2297,19 @@ "xhr-request-promise": "^0.1.2" } }, + "ethereum-bloom-filters": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", + "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", + "requires": { + "js-sha3": "^0.8.0" + } + }, "ethereum-ens": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/ethereum-ens/-/ethereum-ens-0.8.0.tgz", "integrity": "sha512-a8cBTF4AWw1Q1Y37V1LSCS9pRY4Mh3f8vCg5cbXCCEJ3eno1hbI/+Ccv9SZLISYpqQhaglP3Bxb/34lS4Qf7Bg==", + "dev": true, "requires": { "bluebird": "^3.4.7", "eth-ens-namehash": "^2.0.0", @@ -1606,7 +2322,8 @@ "js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true } } }, @@ -1619,6 +2336,11 @@ "ethereumjs-util": "^6.0.0" } }, + "ethereumjs-common": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.1.tgz", + "integrity": "sha512-aVUPRLgmXORGXXEVkFYgPhr9TGtpBY2tGhZ9Uh0A3lIUzUDr1x6kQx33SbjPUkLkX3eniPQnIL/2psjkjrOfcQ==" + }, "ethereumjs-testrpc-sc": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz", @@ -1628,6 +2350,15 @@ "source-map-support": "^0.5.3" } }, + "ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "requires": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, "ethereumjs-util": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", @@ -1705,6 +2436,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/ethjs-abi/-/ethjs-abi-0.2.1.tgz", "integrity": "sha1-4KepOn6BFjqUR3utVu3lJKtt5TM=", + "dev": true, "requires": { "bn.js": "4.11.6", "js-sha3": "0.5.5", @@ -1714,12 +2446,14 @@ "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "dev": true }, "js-sha3": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", - "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=", + "dev": true } } }, @@ -1798,6 +2532,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/exorcist/-/exorcist-1.0.1.tgz", "integrity": "sha1-eTFuPEiFhFSQ97tAXA5bXbEWfFI=", + "dev": true, "requires": { "is-stream": "~1.1.0", "minimist": "0.0.5", @@ -1808,12 +2543,14 @@ "minimist": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", - "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" + "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=", + "dev": true }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { "minimist": "^1.2.5" }, @@ -1821,7 +2558,8 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true } } } @@ -2700,6 +3438,680 @@ } } }, + "ganache-cli": { + "version": "6.10.0-beta.2", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.10.0-beta.2.tgz", + "integrity": "sha512-mJZuwl5W7WLRGrILrmM8hOGCwy98L5dymOpHc5rg4Dqosa6TE+M+qPJPXbWH78jtbUyrbKERZc3E5YpNIfl8Ow==", + "dev": true, + "requires": { + "ethereumjs-util": "6.1.0", + "scrypt": "6.0.3", + "source-map-support": "0.5.12", + "yargs": "13.2.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "bindings": { + "version": "1.5.0", + "bundled": true, + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip66": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bn.js": { + "version": "4.11.8", + "bundled": true, + "dev": true + }, + "brorand": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "bundled": true, + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true, + "dev": true + }, + "create-hash": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "drbg.js": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "elliptic": { + "version": "6.5.0", + "bundled": true, + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "bundled": true, + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "ethereumjs-util": { + "version": "6.1.0", + "bundled": true, + "dev": true, + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "ethjs-util": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "hash-base": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-hex-prefixed": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "keccak": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "nan": { + "version": "2.14.0", + "bundled": true, + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "ripemd160": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.3", + "bundled": true, + "dev": true, + "requires": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "bundled": true, + "dev": true + }, + "secp256k1": { + "version": "3.7.1", + "bundled": true, + "dev": true, + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + } + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "source-map": { + "version": "0.6.1", + "bundled": true, + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "bundled": true, + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "string-width": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "strip-hex-prefix": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "13.2.4", + "bundled": true, + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -2709,7 +4121,8 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true }, "get-stream": { "version": "4.1.0", @@ -2951,8 +4364,7 @@ "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "http-cache-semantics": { "version": "4.1.0", @@ -3407,6 +4819,14 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha1-py8hfcSvxGKf/1/rME3BvVGi89I=", + "requires": { + "delimit-stream": "0.1.0" + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -3508,7 +4928,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -3517,8 +4936,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" } } }, @@ -3535,7 +4953,8 @@ "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true }, "lodash.isequal": { "version": "4.5.0", @@ -3903,6 +5322,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/mold-source-map/-/mold-source-map-0.4.0.tgz", "integrity": "sha1-z2fgsxxHq5uttcnCVlGGISe7gxc=", + "dev": true, "requires": { "convert-source-map": "^1.1.0", "through": "~2.2.7" @@ -3911,7 +5331,8 @@ "through": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", - "integrity": "sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0=" + "integrity": "sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0=", + "dev": true } } }, @@ -3985,6 +5406,11 @@ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, + "nofilter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.3.tgz", + "integrity": "sha512-FlUlqwRK6reQCaFLAhMcF+6VkVG2caYjKQY3YsRDTl4/SEch595Qb3oLjJRDr8dkHAAOVj2pOx3VknfnSgkE5g==" + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -4162,19 +5588,19 @@ "wrappy": "1" } }, - "openzeppelin-test-helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/openzeppelin-test-helpers/-/openzeppelin-test-helpers-0.5.1.tgz", - "integrity": "sha512-xIMusuVCKXfR+qwbyiXpV7UaqaW3H/Q3axQ2nSce8o3R9TQoxrZdbKvMZdJdg6Ro4cpRDQ3yZtniz4vSIbSZHg==", + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", "requires": { - "@truffle/contract": "^4.0.35", - "ansi-colors": "^3.2.3", - "chai-bn": "^0.2.0", - "ethjs-abi": "^0.2.1", - "lodash.flatten": "^4.4.0", - "semver": "^5.6.0", - "web3": "^1.2.1", - "web3-utils": "^1.2.1" + "mimic-fn": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + } } }, "optionator": { @@ -4219,7 +5645,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "requires": { "p-try": "^1.0.0" } @@ -4228,7 +5653,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -4244,13 +5668,13 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true }, "parse-asn1": { "version": "5.1.5", @@ -4347,7 +5771,8 @@ "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true }, "pbkdf2": { "version": "3.0.17", @@ -5062,6 +6487,15 @@ "lowercase-keys": "^1.0.0" } }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -5112,11 +6546,36 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.0.8" + } + }, "scrypt-js": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" }, + "scrypt-shim": { + "version": "github:web3-js/scrypt-shim#aafdadda13e660e25e1c525d1f5b2443f5eb1ebb", + "from": "github:web3-js/scrypt-shim", + "requires": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "scryptsy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", @@ -5319,8 +6778,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-concat": { "version": "1.0.0", @@ -5841,6 +7299,75 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, + "spinnies": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/spinnies/-/spinnies-0.4.3.tgz", + "integrity": "sha512-TTA2vWXrXJpfThWAl2t2hchBnCMI1JM5Wmb2uyI7Zkefdw/xO98LDy6/SBYwQPiYXL3swx3Eb44ZxgoS8X5wpA==", + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^3.0.0", + "strip-ansi": "^5.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6231,6 +7758,28 @@ "lodash.isequal": "^4.5.0" } }, + "truffle-flattener": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.4.4.tgz", + "integrity": "sha512-S/WmvubzlUj1mn56wEI6yo1bmPpKDNdEe5rtyVC1C5iNfZWobD/V69pAYI15IBDJrDqUyh+iXgpTkzov50zpQw==", + "requires": { + "@resolver-engine/imports-fs": "^0.2.2", + "@solidity-parser/parser": "^0.6.0", + "find-up": "^2.1.0", + "mkdirp": "^1.0.4", + "tsort": "0.0.1" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + } + } + }, "truffle-hdwallet-provider": { "version": "1.0.17", "resolved": "https://registry.npmjs.org/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.17.tgz", @@ -6266,6 +7815,17 @@ "querystring": "^0.2.0" } }, + "try-require": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/try-require/-/try-require-1.2.1.tgz", + "integrity": "sha1-NEiaLKwMCcHMEO2RugEVlNQzO+I=", + "dev": true + }, + "tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6296,7 +7856,8 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true }, "type-is": { "version": "1.6.18", diff --git a/package.json b/package.json index 0acdd5f..946081a 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,11 @@ "main": "truffle-config.js", "directories": {}, "scripts": { - "test": "npm run ganache sleep 5 && truffle test && npm run stop", + "test": "truffle test", "coverage": "./node_modules/.bin/solidity-coverage", "solium": "solium -d contracts/", - "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build" + "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build", + "ganache": "ganache-cli --deterministic --unlock 0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c -f https://mainnet.infura.io/v3/" }, "repository": { "type": "git", @@ -35,6 +36,8 @@ "truffle-verify": "^1.0.8" }, "devDependencies": { + "@openzeppelin/test-helpers": "^0.5.6", + "ganache-cli": "^6.10.0-beta.2", "sol-merger": "^2.0.1", "solidity-coverage": "0.5.11", "solium": "1.2.3" diff --git a/test/CurveProtocol.js b/test/CurveProtocol.js index 512af0e..53c8bf0 100644 --- a/test/CurveProtocol.js +++ b/test/CurveProtocol.js @@ -2,7 +2,7 @@ const CurveProtocol = artifacts.require('CurveProtocol') const daiABI = require('./abi/dai'); const erc20 = require('./abi/erc20') const swap_abi = require('./abi/swap') -const { ether, balance } = require('openzeppelin-test-helpers'); +const { ether, balance } = require('@openzeppelin/test-helpers'); const BN = require('bn.js') @@ -24,99 +24,106 @@ const swapContract = new web3.eth.Contract(swap_abi, swap) const swapToken = '0xC25a3A3b969415c80451098fa907EC722572917F' const tokenContract = new web3.eth.Contract(erc20, swapToken) - - contract('Curve Protocol', async accounts => { + it('should send ether to the user address', async () => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() + const ethBalanceBefore = await balance.current(userAddress); + // Send 0.1 eth to userAddress to have gas to send an ERC20 tx. + await web3.eth.sendTransaction({ + from: accounts[0], + to: userAddress, + value: ether('0.1') + }); + const ethBalanceAfter = await balance.current(userAddress); + expect(+ethBalanceAfter - +ethBalanceBefore).to.equal(+ether('0.1')) + }); - it('should send ether to the DAI address', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() - // Send 0.1 eth to userAddress to have gas to send an ERC20 tx. - await web3.eth.sendTransaction({ - from: accounts[0], - to: userAddress, - value: ether('0.1') - }); - const ethBalance = await balance.current(userAddress); - expect(+ethBalance).to.be.at.least(+ether('0.1')) - }); + it('should transfer DAI to CurveProtocol', async () => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() + // Get 100 DAI for first 5 accounts + // daiAddress is passed to ganache-cli with flag `--unlock` + // so we can use the `transfer` method + // + // Note: This only works as userAddress has 2546221640728945323079640 Dai, + // should remove this dependence in the future + const daiBalanceUser = await daiContract.methods.balanceOf(userAddress).call(); + await daiContract.methods + .transfer(contract.address, ether('100').toString()) + .send({ from: userAddress, gasLimit: 800000 }); + const daiBalance = await daiContract.methods.balanceOf(contract.address).call(); + expect(+daiBalance).to.be.at.least(+ether('100')) + }); - it('should transfer DAI to CurveProtocol', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() - // Get 100 DAI for first 5 accounts - // daiAddress is passed to ganache-cli with flag `--unlock` - // so we can use the `transfer` method - await daiContract.methods - .transfer(contract.address, ether('100').toString()) - .send({ from: userAddress, gasLimit: 800000 }); - const daiBalance = await daiContract.methods.balanceOf(contract.address).call(); - expect(+daiBalance).to.be.at.least(+ether('100')) - }); + it('should approve DAI to CurveProtocol', async() => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() - it('should approve DAI to CurveProtocol', async() => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() + await daiContract.methods + .approve(contract.address, ether('100').toString()) + .send({ from: account, gasLimit: 800000 }); + const daiAllowance = await daiContract.methods.allowance(account, contract.address).call() + expect(+daiAllowance).to.be.at.least(+ether('100')) + }); - await daiContract.methods - .approve(contract.address, ether('100').toString()) - .send({ from: account, gasLimit: 800000 }); - const daiAllowance = await daiContract.methods.allowance(account, contract.address).call() - expect(+daiAllowance).to.be.at.least(+ether('100')) - }); + /* Deprecated as CurveProtocol is not ICurve and exchange has been implemented into sell method + it('should exchange', async () => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() - it('should exchange', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() + // Get 100 DAI for first 5 accounts + console.log('before'); + let get_dy = await contract.get_dy.call(0, 1, ether('1').toString()) + console.log('after'); + let min_dy = +get_dy * 0.99 + let receipt = await contract.exchange(0, 1, ether('1').toString(), 1, { from: account }) + let buyAmount = receipt.logs[0].args.buyAmount.toString() + expect(+buyAmount).to.be.at.least(min_dy); + }); + */ - // Get 100 DAI for first 5 accounts - let get_dy = await contract.get_dy.call(0, 1, ether('1').toString()) - let min_dy = +get_dy * 0.99 - let receipt = await contract.exchange(0, 1, ether('1').toString(), 1, { from: account }) - let buyAmount = receipt.logs[0].args.buyAmount.toString() - expect(+buyAmount).to.be.at.least(min_dy); + /* Deprecated as CurveProtocol is not ICurve and calc_token_amount has been implemented into withdraw method + it('should add liquidity', async () => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() - }); + let amounts = [ether('1').toString(), 0, 0, 0] + let token_amount = await contract.calc_token_amount.call(amounts, true) - it('should add liquidity', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() + let receipt = await contract.add_liquidity(amounts, 1, { from: account }) + let mintAmount = receipt.logs[0].args.mintAmount.toString() + expect(+mintAmount).to.be.at.least(+mintAmount) + }) - let amounts = [ether('1').toString(), 0, 0, 0] - let token_amount = await contract.calc_token_amount.call(amounts, true) + it('should remove liquidity imbalance', async () => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() - let receipt = await contract.add_liquidity(amounts, 1, { from: account }) - let mintAmount = receipt.logs[0].args.mintAmount.toString() - expect(+mintAmount).to.be.at.least(+mintAmount) - }) + let tokenBalance = await tokenContract.methods.balanceOf(contract.address).call() + let receipt = await contract.remove_liquidity_imbalance(["100000000000", 0, 0, 0], { from: account }) + let burnAmount = receipt.logs[0].args.burnAmount.toString() + let tokenBalanceAfter = await tokenContract.methods.balanceOf(contract.address).call() - it('should remove liquidity imbalance', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() + //weird Ganache errors sometimes "cannot decode event" + console.log(+tokenBalance, +tokenBalanceAfter, +burnAmount) + //expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount)) - let tokenBalance = await tokenContract.methods.balanceOf(contract.address).call() - let receipt = await contract.remove_liquidity_imbalance(["100000000000", 0, 0, 0], { from: account }) - let burnAmount = receipt.logs[0].args.burnAmount.toString() - let tokenBalanceAfter = await tokenContract.methods.balanceOf(contract.address).call() + }) - //weird Ganache errors sometimes "cannot decode event" - console.log(+tokenBalance, +tokenBalanceAfter, +burnAmount) - //expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount)) + it('should remove liquidity in one coin', async() => { + let account = accounts[0] + let contract = await CurveProtocol.deployed() - }) + let daiBalance = await daiContract.methods.balanceOf(contract.address).call() + let receipt = await contract.remove_liquidity_one_coin("100000000000", 0, 1, { from: account }) + let withdrawnAmount = receipt.logs[0].args.withdrawnAmount.toString() + let daiBalanceAfter = await daiContract.methods.balanceOf(contract.address).call() - it('should remove liquidity in one coin', async() => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() - - let daiBalance = await daiContract.methods.balanceOf(contract.address).call() - let receipt = await contract.remove_liquidity_one_coin("100000000000", 0, 1, { from: account }) - let withdrawnAmount = receipt.logs[0].args.withdrawnAmount.toString() - let daiBalanceAfter = await daiContract.methods.balanceOf(contract.address).call() - - //weird Ganache errors sometimes "cannot decode event" - console.log(+daiBalance, +daiBalanceAfter, +withdrawnAmount) - //expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount)); - }) -}); \ No newline at end of file + //weird Ganache errors sometimes "cannot decode event" + console.log(+daiBalance, +daiBalanceAfter, +withdrawnAmount) + //expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount)); + }) + */ +}); diff --git a/truffle-config.js b/truffle-config.js index 71a9947..c1652ad 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -54,6 +54,12 @@ module.exports = { port: 8545, // Standard Ethereum port (default: none) network_id: "*", // Any network (default: none) }, + // Tenderly Proxy + proxy: { + host: "127.0.0.1", // Localhost (default: none) + port: 9545, // Standard Ethereum port (default: none) + network_id: "*", // Any network (default: none) + }, // Another network with more advanced options... // advanced: { @@ -108,7 +114,7 @@ module.exports = { // Configure your compilers compilers: { solc: { - version: "v0.6.0", // Fetch exact version from solc-bin (default: truffle's version) + version: "v0.6.2", // Fetch exact version from solc-bin (default: truffle's version) // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) // settings: { // See the solidity docs for advice about optimization and evmVersion // optimizer: { From e5f418157faeee1c1f662ef382b2cc8c26609944 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Tue, 30 Jun 2020 02:15:35 +1000 Subject: [PATCH 02/16] Updated math.sol to use SafeMath from OZ; update migration to deploy CurveSBTCProtocol; Added Curvesbtc.sol sell method and got it compiled; --- contracts/common/math.sol | 53 +++++++------ contracts/connectors/curvesbtc.sol | 115 +++++++++++++++++++++++++++++ migrations/2_deploy_connector.js | 6 +- 3 files changed, 148 insertions(+), 26 deletions(-) create mode 100644 contracts/connectors/curvesbtc.sol diff --git a/contracts/common/math.sol b/contracts/common/math.sol index b80bf47..cc3e20e 100644 --- a/contracts/common/math.sol +++ b/contracts/common/math.sol @@ -1,36 +1,41 @@ pragma solidity ^0.6.0; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + contract DSMath { - uint constant WAD = 10 ** 18; - uint constant RAY = 10 ** 27; + uint constant WAD = 10 ** 18; + uint constant RAY = 10 ** 27; - function add(uint x, uint y) internal pure returns (uint z) { - require((z = x + y) >= x, "math-not-safe"); - } + function add(uint x, uint y) internal pure returns (uint z) { + SafeMath.add(x, y); + } - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, "ds-math-sub-underflow"); - } + function sub(uint x, uint y) internal pure returns (uint z) { + SafeMath.sub(x, y); + } - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, "math-not-safe"); - } + function mul(uint x, uint y) internal pure returns (uint z) { + SafeMath.mul(x, y); + } + function div(uint x, uint y) internal pure returns (uint z) { + SafeMath.div(x, y); + } - function wmul(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, y), WAD / 2) / WAD; - } + function wmul(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, y), WAD / 2) / WAD; + } - function wdiv(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, WAD), y / 2) / y; - } + function wdiv(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, WAD), y / 2) / y; + } - function rdiv(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, RAY), y / 2) / y; - } + function rdiv(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, RAY), y / 2) / y; + } - function rmul(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, y), RAY / 2) / RAY; - } + function rmul(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, y), RAY / 2) / RAY; + } -} \ No newline at end of file +} diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol new file mode 100644 index 0000000..5a802a4 --- /dev/null +++ b/contracts/connectors/curvesbtc.sol @@ -0,0 +1,115 @@ +pragma solidity ^0.6.0; + +// import files from common directory +import { MemoryInterface, EventInterface} from "../common/interfaces.sol"; +import { Stores } from "../common/stores.sol"; +import { DSMath } from "../common/math.sol"; + +// import files from OZ +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {SafeCast} from "@openzeppelin/contracts/utils/SafeCast.sol"; + +interface ICurve { + function coins(int128 tokenId) external view returns (address token); + function calc_token_amount(uint256[3] calldata amounts, bool deposit) external returns (uint256 amount); + function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external; + function get_dy(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt) external returns (uint256 buyTokenAmt); + function exchange(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt, uint256 minBuyToken) external; + function remove_liquidity_imbalance(uint256[3] calldata amounts, uint256 max_burn_amount) external; + function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external returns (uint256 amount); +} + +contract CurveSBTCHelpers is Stores, DSMath{ + /** + * @dev Return Curve Swap Address + */ + function getCurveSwapAddr() internal pure returns (address) { + return 0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714; + } + + /** + * @dev Return Curve Token Address + */ + function getCurveTokenAddr() internal pure returns (address) { + return 0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3; + } + + function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = div(_amt, 10 ** (18 - _dec)); + } + + function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = mul(_amt, 10 ** (18 - _dec)); + } + + function getTokenI(address token) internal pure returns (int128 i) { + if (token == address(0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D)) { + // RenBTC Token + i = 0; + } else if (token == address(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599)) { + // WBTC Token + i = 1; + } else if (token == address(0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6)) { + // SBTC Token + i = 2; + } else { + revert("token-not-found."); + } + } +} + +contract CurveSBTCProtocol is CurveSBTCHelpers { + + // Events + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + event LogDeposit(address token, uint256 amt, uint256 mintAmt, uint256 getId, uint256 setId); + event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId, uint256 setId); + + /** + * @dev Sell Stable ERC20_Token. + * @param buyAddr buying token address. + * @param sellAddr selling token amount. + * @param sellAmt selling token amount. + * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint getId, + uint setId + ) external payable { + uint _sellAmt = getUint(getId, sellAmt); + ICurve curve = ICurve(getCurveSwapAddr()); + ERC20 _buyToken = ERC20(buyAddr); + ERC20 _sellToken = ERC20(sellAddr); + _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt; + _sellToken.approve(address(curve), _sellAmt); + + uint _slippageAmt = convert18ToDec(_buyToken.decimals(), wmul(unitAmt, convertTo18(_sellToken.decimals(), _sellAmt))); + + uint intialBal = _buyToken.balanceOf(address(this)); + curve.exchange(getTokenI(sellAddr), getTokenI(buyAddr), _sellAmt, _slippageAmt); + uint finalBal = _buyToken.balanceOf(address(this)); + + uint _buyAmt = sub(finalBal, intialBal); + + setUint(setId, _buyAmt); + + emit LogSell(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } + +} diff --git a/migrations/2_deploy_connector.js b/migrations/2_deploy_connector.js index f3bea19..d3f69ce 100644 --- a/migrations/2_deploy_connector.js +++ b/migrations/2_deploy_connector.js @@ -1,5 +1,7 @@ -const Connector = artifacts.require("CurveProtocol"); // Change the Connector name while deploying. +const CurveProtocol = artifacts.require("CurveProtocol"); +const CurveSBTCProtocol = artifacts.require("CurveSBTCProtocol"); module.exports = function(deployer) { - deployer.deploy(Connector); + deployer.deploy(CurveProtocol); + deployer.deploy(CurveSBTCProtocol); }; From b3da8dcba0013f32a0b49e2d10df3aa6ba40046f Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Tue, 30 Jun 2020 23:16:15 +1000 Subject: [PATCH 03/16] added studydefi/money-legos for testing; fixed CurveProtocol test; added CurveSBTCProtocol and sell function with test but currently failed and revert with unknown reason --- package-lock.json | 17 +++++++++ package.json | 1 + test/CurveProtocol.js | 31 ++++++++-------- test/CurveSBTCProtocol.js | 77 +++++++++++++++++++++++++++++++++++++++ test/abi/sbtc.json | 1 + 5 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 test/CurveSBTCProtocol.js create mode 100644 test/abi/sbtc.json diff --git a/package-lock.json b/package-lock.json index bc00856..9991825 100644 --- a/package-lock.json +++ b/package-lock.json @@ -661,6 +661,23 @@ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.6.2.tgz", "integrity": "sha512-kUVUvrqttndeprLoXjI5arWHeiP3uh4XODAKbG+ZaWHCVQeelxCbnXBeWxZ2BPHdXgH0xR9dU1b916JhDhbgAA==" }, + "@studydefi/money-legos": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@studydefi/money-legos/-/money-legos-2.3.5.tgz", + "integrity": "sha512-Whfsw+Ka5PCX8u7za0DOnb3j7DqPQ0QW2SjtjrC4drP+MRpq6ANdxTLgAqYU2e5BZ3/DrDZ6MGTajMCPKXoxZw==", + "dev": true, + "requires": { + "@openzeppelin/contracts": "^2.5.0" + }, + "dependencies": { + "@openzeppelin/contracts": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-2.5.1.tgz", + "integrity": "sha512-qIy6tLx8rtybEsIOAlrM4J/85s2q2nPkDqj/Rx46VakBZ0LwtFhXIVub96LXHczQX0vaqmAueDqNPXtbSXSaYQ==", + "dev": true + } + } + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", diff --git a/package.json b/package.json index 946081a..4f1376c 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "devDependencies": { "@openzeppelin/test-helpers": "^0.5.6", + "@studydefi/money-legos": "^2.3.5", "ganache-cli": "^6.10.0-beta.2", "sol-merger": "^2.0.1", "solidity-coverage": "0.5.11", diff --git a/test/CurveProtocol.js b/test/CurveProtocol.js index 53c8bf0..29325fd 100644 --- a/test/CurveProtocol.js +++ b/test/CurveProtocol.js @@ -25,10 +25,14 @@ const swapToken = '0xC25a3A3b969415c80451098fa907EC722572917F' const tokenContract = new web3.eth.Contract(erc20, swapToken) contract('Curve Protocol', async accounts => { + let account, contract; + + beforeEach(async function() { + account = accounts[0] + contract = await CurveProtocol.deployed() + }); it('should send ether to the user address', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() const ethBalanceBefore = await balance.current(userAddress); // Send 0.1 eth to userAddress to have gas to send an ERC20 tx. await web3.eth.sendTransaction({ @@ -41,8 +45,6 @@ contract('Curve Protocol', async accounts => { }); it('should transfer DAI to CurveProtocol', async () => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() // Get 100 DAI for first 5 accounts // daiAddress is passed to ganache-cli with flag `--unlock` // so we can use the `transfer` method @@ -58,14 +60,11 @@ contract('Curve Protocol', async accounts => { }); it('should approve DAI to CurveProtocol', async() => { - let account = accounts[0] - let contract = await CurveProtocol.deployed() - await daiContract.methods - .approve(contract.address, ether('100').toString()) - .send({ from: account, gasLimit: 800000 }); - const daiAllowance = await daiContract.methods.allowance(account, contract.address).call() - expect(+daiAllowance).to.be.at.least(+ether('100')) + .approve(contract.address, ether('100').toString()) + .send({ from: account, gasLimit: 800000 }); + const daiAllowance = await daiContract.methods.allowance(account, contract.address).call() + expect(+daiAllowance).to.be.at.least(+ether('100')) }); /* Deprecated as CurveProtocol is not ICurve and exchange has been implemented into sell method @@ -84,7 +83,7 @@ contract('Curve Protocol', async accounts => { }); */ - /* Deprecated as CurveProtocol is not ICurve and calc_token_amount has been implemented into withdraw method + /* Deprecated as CurveProtocol is not ICurve and calc_token_amount has been implemented into withdraw method it('should add liquidity', async () => { let account = accounts[0] let contract = await CurveProtocol.deployed() @@ -106,9 +105,9 @@ contract('Curve Protocol', async accounts => { let burnAmount = receipt.logs[0].args.burnAmount.toString() let tokenBalanceAfter = await tokenContract.methods.balanceOf(contract.address).call() - //weird Ganache errors sometimes "cannot decode event" +//weird Ganache errors sometimes "cannot decode event" console.log(+tokenBalance, +tokenBalanceAfter, +burnAmount) - //expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount)) +//expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount)) }) @@ -121,9 +120,9 @@ contract('Curve Protocol', async accounts => { let withdrawnAmount = receipt.logs[0].args.withdrawnAmount.toString() let daiBalanceAfter = await daiContract.methods.balanceOf(contract.address).call() - //weird Ganache errors sometimes "cannot decode event" +//weird Ganache errors sometimes "cannot decode event" console.log(+daiBalance, +daiBalanceAfter, +withdrawnAmount) - //expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount)); +//expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount)); }) */ }); diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js new file mode 100644 index 0000000..63a8771 --- /dev/null +++ b/test/CurveSBTCProtocol.js @@ -0,0 +1,77 @@ +const { + BN, // Big Number support + expectEvent, // Assertions for emitted events + expectRevert, // Assertions for transactions that should fail + balance, + ether +} = require('@openzeppelin/test-helpers'); + +const CurveSBTCProtocol = artifacts.require('CurveSBTCProtocol'); +const erc20 = require("@studydefi/money-legos/erc20"); +const uniswap = require("@studydefi/money-legos/uniswap"); +const sbtcABI = require("./abi/sbtc.json"); + +contract('CurveSBTCProtocol', async accounts => { + const [sender, receiver] = accounts; + let contract; + + beforeEach(async function () { + contract = await CurveSBTCProtocol.deployed() + + let wbtcContract = new web3.eth.Contract(erc20.wbtc.abi, erc20.wbtc.address); + + let uniswapFactory = new web3.eth.Contract( + uniswap.factory.abi, + uniswap.factory.address + ); + + const wbtcExchangeAddress = await uniswapFactory.methods.getExchange( + erc20.wbtc.address, + ).call(); + + const wbtcExchange = new web3.eth.Contract( + uniswap.exchange.abi, + wbtcExchangeAddress + ); + + const wbtcBefore = await wbtcContract.methods.balanceOf(sender).call(); + + await wbtcExchange.methods.ethToTokenSwapInput( + 1, // min amount of token retrieved + 2525644800, // random timestamp in the future (year 2050) + ).send( + { + gas: 4000000, + value: ether("5"), + from: sender + } + ); + + let wbtcAfter = await wbtcContract.methods.balanceOf(sender).call(); + + expect(wbtcAfter - wbtcBefore).to.be.at.least(10000000); + }); + + it('can sell WBTC for SBTC', async function () { + const sbtcContract = new web3.eth.Contract(sbtcABI, "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6"); + + const sbtcBefore = await sbtcContract.methods.balanceOf(sender).call(); + + const tx = await contract.sell( + "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6", + erc20.wbtc.address, + 10000000, + ( 0.09 / 0.1 * 1e18 ).toString(), + 0, + 0, + { + gas: 4000000, + from: sender + } + ); + console.log(tx); + + const sbtcAfter = await sbtcContract.methods.balanceOf(sender).call(); + expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); + }); +}); diff --git a/test/abi/sbtc.json b/test/abi/sbtc.json new file mode 100644 index 0000000..c227105 --- /dev/null +++ b/test/abi/sbtc.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_target","type":"address"}],"name":"setTarget","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"callData","type":"bytes"},{"name":"numTopics","type":"uint256"},{"name":"topic1","type":"bytes32"},{"name":"topic2","type":"bytes32"},{"name":"topic3","type":"bytes32"},{"name":"topic4","type":"bytes32"}],"name":"_emit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"useDELEGATECALL","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"value","type":"bool"}],"name":"setUseDELEGATECALL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"target","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_owner","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newTarget","type":"address"}],"name":"TargetUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"}] From 0ff06b28f165d817bdbc2957bd1b285383a428c8 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Wed, 1 Jul 2020 00:07:15 +1000 Subject: [PATCH 04/16] added deposit method and test; --- contracts/connectors/curvesbtc.sol | 44 ++++++++++++++++++++++++++++++ test/CurveSBTCProtocol.js | 26 ++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index 5a802a4..e796188 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -112,4 +112,48 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { emitEvent(_eventCode, _eventParam); } + /** + * @dev Deposit Token. + * @param token token address. + * @param amt token amount. + * @param unitAmt unit amount of curve_amt/token_amt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function deposit( + address token, + uint amt, + uint unitAmt, + uint getId, + uint setId + ) external payable { + uint256 _amt = getUint(getId, amt); + ERC20 tokenContract = ERC20(token); + + _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; + uint[3] memory _amts; + _amts[uint(getTokenI(token))] = _amt; + + tokenContract.approve(getCurveSwapAddr(), _amt); + + uint _amt18 = convertTo18(tokenContract.decimals(), _amt); + uint _slippageAmt = wmul(unitAmt, _amt18); + + ERC20 curveTokenContract = ERC20(getCurveTokenAddr()); + uint initialCurveBal = curveTokenContract.balanceOf(address(this)); + + ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt); + + uint finalCurveBal = curveTokenContract.balanceOf(address(this)); + + uint mintAmt = sub(finalCurveBal, initialCurveBal); + + setUint(setId, mintAmt); + + emit LogDeposit(token, _amt, mintAmt, getId, setId); + bytes32 _eventCode = keccak256("LogDeposit(address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(token, _amt, mintAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } + } diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index 63a8771..adb3071 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -10,6 +10,7 @@ const CurveSBTCProtocol = artifacts.require('CurveSBTCProtocol'); const erc20 = require("@studydefi/money-legos/erc20"); const uniswap = require("@studydefi/money-legos/uniswap"); const sbtcABI = require("./abi/sbtc.json"); +const erc20ABI = require("./abi/erc20.js"); contract('CurveSBTCProtocol', async accounts => { const [sender, receiver] = accounts; @@ -74,4 +75,29 @@ contract('CurveSBTCProtocol', async accounts => { const sbtcAfter = await sbtcContract.methods.balanceOf(sender).call(); expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); }); + + it('can add liquidity for wbtc', async function() { + const curveTokenContract = new web3.eth.Contract( + erc20ABI, + "0x075b1bb99792c9e1041ba13afef80c91a1e70fb3" + ) + + const tx = await contract.deposit( + erc20.wbtc.address, + 10000000, + ( 0.09 / 0.1 * 1e18 ).toString(), + 0, + 0, + { + gas: 4000000, + from: sender + } + ); + console.log(tx); + + const balance = await curveTokenContract.methods.balanceOf(sender); + + expect(balance).to.be.at.least(ether("0.09")); + + }); }); From a24ee929fda41a0067ec56e8d7f0c7a39949f89e Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Wed, 1 Jul 2020 00:17:20 +1000 Subject: [PATCH 05/16] added method withdraw and test; --- contracts/connectors/curvesbtc.sol | 48 ++++++++++++++++++++++++++++++ test/CurveSBTCProtocol.js | 25 +++++++++++++--- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index e796188..f599d86 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -156,4 +156,52 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { emitEvent(_eventCode, _eventParam); } + /** + * @dev Withdraw Token. + * @param token token address. + * @param amt token amount. + * @param unitAmt unit amount of curve_amt/token_amt with slippage. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function withdraw( + address token, + uint256 amt, + uint256 unitAmt, + uint getId, + uint setId + ) external payable { + uint _amt = getUint(getId, amt); + int128 tokenId = getTokenI(token); + + ERC20 curveTokenContract = ERC20(getCurveTokenAddr()); + ICurve curveSwap = ICurve(getCurveSwapAddr()); + + uint _curveAmt; + uint[3] memory _amts; + if (_amt == uint(-1)) { + _curveAmt = curveTokenContract.balanceOf(address(this)); + _amt = curveSwap.calc_withdraw_one_coin(_curveAmt, tokenId); + _amts[uint(tokenId)] = _amt; + } else { + _amts[uint(tokenId)] = _amt; + _curveAmt = curveSwap.calc_token_amount(_amts, false); + } + + uint _amt18 = convertTo18(ERC20(token).decimals(), _amt); + uint _slippageAmt = wmul(unitAmt, _amt18); + + curveTokenContract.approve(address(curveSwap), 0); + curveTokenContract.approve(address(curveSwap), _slippageAmt); + + curveSwap.remove_liquidity_imbalance(_amts, _slippageAmt); + + setUint(setId, _amt); + + emit LogWithdraw(token, _amt, _curveAmt, getId, setId); + bytes32 _eventCode = keccak256("LogWithdraw(address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId); + emitEvent(_eventCode, _eventParam); + } + } diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index adb3071..83c820e 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -82,7 +82,7 @@ contract('CurveSBTCProtocol', async accounts => { "0x075b1bb99792c9e1041ba13afef80c91a1e70fb3" ) - const tx = await contract.deposit( + const txDeposit = await contract.deposit( erc20.wbtc.address, 10000000, ( 0.09 / 0.1 * 1e18 ).toString(), @@ -93,11 +93,28 @@ contract('CurveSBTCProtocol', async accounts => { from: sender } ); - console.log(tx); + console.log(txDeposit); - const balance = await curveTokenContract.methods.balanceOf(sender); + const balanceDeposit = await curveTokenContract.methods.balanceOf(sender); - expect(balance).to.be.at.least(ether("0.09")); + expect(balanceDeposit).to.be.at.least(ether("0.09")); + const txWithdraw = await contract.withdraw( + erc20.wbtc.address, + 10000000, + ( 0.09 / 0.1 * 1e18 ).toString(), + 0, + 0, + { + gas: 4000000, + from: sender + } + ); + console.log(txWithdraw); + + const balanceWithdraw = await curveTokenContract.methods.balanceOf(sender); + + expect(balanceWithdraw).to.equal(0); }); + }); From 60f15afeef7044b918cf20b4ea1485903d902b2f Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Wed, 1 Jul 2020 00:23:19 +1000 Subject: [PATCH 06/16] update test title --- test/CurveSBTCProtocol.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index 83c820e..e163d93 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -76,7 +76,7 @@ contract('CurveSBTCProtocol', async accounts => { expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); }); - it('can add liquidity for wbtc', async function() { + it('can add and remove liquidity for wbtc', async function() { const curveTokenContract = new web3.eth.Contract( erc20ABI, "0x075b1bb99792c9e1041ba13afef80c91a1e70fb3" From 66edeb2e19afafaed0e9c8292b772a978b7244a6 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Thu, 2 Jul 2020 10:26:47 +0530 Subject: [PATCH 07/16] Fixed safemath issue --- contracts/common/math.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/common/math.sol b/contracts/common/math.sol index cc3e20e..63b5880 100644 --- a/contracts/common/math.sol +++ b/contracts/common/math.sol @@ -7,19 +7,19 @@ contract DSMath { uint constant RAY = 10 ** 27; function add(uint x, uint y) internal pure returns (uint z) { - SafeMath.add(x, y); + z = SafeMath.add(x, y); } function sub(uint x, uint y) internal pure returns (uint z) { - SafeMath.sub(x, y); + z = SafeMath.sub(x, y); } function mul(uint x, uint y) internal pure returns (uint z) { - SafeMath.mul(x, y); + z = SafeMath.mul(x, y); } function div(uint x, uint y) internal pure returns (uint z) { - SafeMath.div(x, y); + z = SafeMath.div(x, y); } function wmul(uint x, uint y) internal pure returns (uint z) { From c639cdc6a9624bc0989f62dd8c6a74ff82b4fb2c Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Thu, 2 Jul 2020 10:27:01 +0530 Subject: [PATCH 08/16] Done with curve btc connector --- contracts/connectors/curvesbtc.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index f599d86..12ecb6e 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -7,7 +7,6 @@ import { DSMath } from "../common/math.sol"; // import files from OZ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import {SafeCast} from "@openzeppelin/contracts/utils/SafeCast.sol"; interface ICurve { function coins(int128 tokenId) external view returns (address token); @@ -73,7 +72,7 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId, uint256 setId); /** - * @dev Sell Stable ERC20_Token. + * @dev Sell ERC20_Token. * @param buyAddr buying token address. * @param sellAddr selling token amount. * @param sellAmt selling token amount. @@ -203,5 +202,9 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId); emitEvent(_eventCode, _eventParam); } - } + +contract ConnectSBTCCurve is CurveSBTCProtocol { + string public name = "Curve-sbtc-v1"; +} + From 7f896a12de7bc73c57dd0c522f6587b1690a5e53 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Sat, 4 Jul 2020 00:43:19 +1000 Subject: [PATCH 09/16] change connectorID method in stores to virtual view; adding connectorID method in connector as override and set model, id in constructor; modify migration to deploy and set model, id; update ganache to unlock master; fixing curveProtocol test to use master address and get dai from uniswap; fixing curveSBTCProtocol test to use cast for the sell connector method; --- contracts/common/stores.sol | 4 +- contracts/connectors/curvesbtc.sol | 11 +++++ migrations/2_deploy_connector.js | 11 +++-- package.json | 2 +- test/CurveProtocol.js | 34 ++++++++++++++- test/CurveSBTCProtocol.js | 67 ++++++++++++++++++++++++------ test/abi/account.json | 1 + test/abi/connectors.json | 1 + 8 files changed, 111 insertions(+), 20 deletions(-) create mode 100644 test/abi/account.json create mode 100644 test/abi/connectors.json diff --git a/contracts/common/stores.sol b/contracts/common/stores.sol index 7926bb7..00daf65 100644 --- a/contracts/common/stores.sol +++ b/contracts/common/stores.sol @@ -51,8 +51,8 @@ contract Stores { /** * @dev Connector Details - needs to be changed before deployment */ - function connectorID() public pure returns(uint model, uint id) { + function connectorID() public virtual view returns(uint model, uint id) { (model, id) = (0, 0); } -} \ No newline at end of file +} diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index 12ecb6e..8d5022f 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -206,5 +206,16 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { contract ConnectSBTCCurve is CurveSBTCProtocol { string public name = "Curve-sbtc-v1"; + uint public _model; + uint public _id; + + constructor (uint model, uint id) public { + _model = model; + _id = id; + } + + function connectorID() public override view returns(uint model, uint id) { + (model, id) = (_model, _id); + } } diff --git a/migrations/2_deploy_connector.js b/migrations/2_deploy_connector.js index d3f69ce..18f5843 100644 --- a/migrations/2_deploy_connector.js +++ b/migrations/2_deploy_connector.js @@ -1,7 +1,12 @@ const CurveProtocol = artifacts.require("CurveProtocol"); -const CurveSBTCProtocol = artifacts.require("CurveSBTCProtocol"); +const ConnectSBTCCurve = artifacts.require("ConnectSBTCCurve"); -module.exports = function(deployer) { +const connectorsABI = require("../test/abi/connectors.json"); +let connectorsAddr = "0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c"; +let connectorInstance = new web3.eth.Contract(connectorsABI, connectorsAddr); + +module.exports = async function(deployer) { deployer.deploy(CurveProtocol); - deployer.deploy(CurveSBTCProtocol); + let connectorLength = await connectorInstance.methods.connectorLength().call(); + deployer.deploy(ConnectSBTCCurve, 1, +connectorLength + 1); }; diff --git a/package.json b/package.json index 4f1376c..a354223 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "coverage": "./node_modules/.bin/solidity-coverage", "solium": "solium -d contracts/", "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build", - "ganache": "ganache-cli --deterministic --unlock 0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c -f https://mainnet.infura.io/v3/" + "ganache": "ganache-cli --deterministic --unlock 0xfcd22438ad6ed564a1c26151df73f6b33b817b56 -f https://mainnet.infura.io/v3/" }, "repository": { "type": "git", diff --git a/test/CurveProtocol.js b/test/CurveProtocol.js index 29325fd..fdda7d3 100644 --- a/test/CurveProtocol.js +++ b/test/CurveProtocol.js @@ -3,6 +3,7 @@ const daiABI = require('./abi/dai'); const erc20 = require('./abi/erc20') const swap_abi = require('./abi/swap') const { ether, balance } = require('@openzeppelin/test-helpers'); +const uniswap = require("@studydefi/money-legos/uniswap"); const BN = require('bn.js') @@ -11,7 +12,7 @@ const expect = chai.expect chai.use(require('chai-bn')(BN)); // userAddress must be unlocked using --unlock ADDRESS -const userAddress = '0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c'; +const userAddress = '0xfcd22438ad6ed564a1c26151df73f6b33b817b56'; const daiAddress = '0x6b175474e89094c44da98b954eedeac495271d0f'; const daiContract = new web3.eth.Contract(daiABI, daiAddress); @@ -30,6 +31,37 @@ contract('Curve Protocol', async accounts => { beforeEach(async function() { account = accounts[0] contract = await CurveProtocol.deployed() + + let uniswapFactory = new web3.eth.Contract( + uniswap.factory.abi, + uniswap.factory.address + ); + + const daiExchangeAddress = await uniswapFactory.methods.getExchange( + daiAddress, + ).call(); + + const daiExchange = new web3.eth.Contract( + uniswap.exchange.abi, + daiExchangeAddress + ); + + const daiBefore = await daiContract.methods.balanceOf(userAddress).call(); + + await daiExchange.methods.ethToTokenSwapInput( + 1, // min amount of token retrieved + 2525644800, // random timestamp in the future (year 2050) + ).send( + { + gas: 4000000, + value: ether("5"), + from: userAddress + } + ); + + let daiAfter = await daiContract.methods.balanceOf(userAddress).call(); + + expect(daiAfter - daiBefore).to.be.at.least(+ether("1000")); }); it('should send ether to the user address', async () => { diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index e163d93..510d0a9 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -6,18 +6,29 @@ const { ether } = require('@openzeppelin/test-helpers'); -const CurveSBTCProtocol = artifacts.require('CurveSBTCProtocol'); +const ConnectSBTCCurve = artifacts.require('ConnectSBTCCurve'); const erc20 = require("@studydefi/money-legos/erc20"); const uniswap = require("@studydefi/money-legos/uniswap"); const sbtcABI = require("./abi/sbtc.json"); const erc20ABI = require("./abi/erc20.js"); +const connectorsABI = require("./abi/connectors.json"); +const accountABI = require("./abi/account.json"); -contract('CurveSBTCProtocol', async accounts => { +contract('ConnectSBTCCurve', async accounts => { const [sender, receiver] = accounts; - let contract; + let masterAddress = "0xfcd22438ad6ed564a1c26151df73f6b33b817b56"; + let accountID = 7; + let dsrAddr = "0xEEB007bea2Bbb0cA6502217E8867f8f7b021B8D5"; + + let connectorsAddr = "0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c"; + let connectorInstance = new web3.eth.Contract(connectorsABI, connectorsAddr); + + // let accountAddr = "0x939Daad09fC4A9B8f8A9352A485DAb2df4F4B3F8"; + let accountInstance = new web3.eth.Contract(accountABI, dsrAddr); + let connectSBTCCurve; beforeEach(async function () { - contract = await CurveSBTCProtocol.deployed() + connectSBTCCurve = await ConnectSBTCCurve.deployed(); let wbtcContract = new web3.eth.Contract(erc20.wbtc.abi, erc20.wbtc.address); @@ -36,6 +47,10 @@ contract('CurveSBTCProtocol', async accounts => { ); const wbtcBefore = await wbtcContract.methods.balanceOf(sender).call(); + console.log("WBTC Before: ", wbtcBefore.toString()); + + const balanceBefore = await web3.eth.getBalance(sender); + console.log("Balance Before: ", balanceBefore.toString()); await wbtcExchange.methods.ethToTokenSwapInput( 1, // min amount of token retrieved @@ -49,38 +64,63 @@ contract('CurveSBTCProtocol', async accounts => { ); let wbtcAfter = await wbtcContract.methods.balanceOf(sender).call(); + console.log("WBTC After: ", wbtcAfter.toString()); + const balanceAfter = await web3.eth.getBalance(sender); + console.log("Balance After: ", balanceAfter.toString()); expect(wbtcAfter - wbtcBefore).to.be.at.least(10000000); + + // send WBTC to master + await wbtcContract.methods.transfer(dsrAddr, 10000000).send({from: sender}); + + // Send ETH to master + await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("50")}); + + let connectorID = await connectSBTCCurve.connectorID(); + + // Enable the the given connector address + await connectorInstance.methods.enable(connectSBTCCurve.address).send({from: masterAddress}); + // check if the give connector address is enabled. + let isEnabled = await connectorInstance.methods.connectors(connectSBTCCurve.address).call(); + assert.ok(isEnabled); }); it('can sell WBTC for SBTC', async function () { const sbtcContract = new web3.eth.Contract(sbtcABI, "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6"); - const sbtcBefore = await sbtcContract.methods.balanceOf(sender).call(); + const sbtcBefore = await sbtcContract.methods.balanceOf(dsrAddr).call(); - const tx = await contract.sell( + const encoded = await connectSBTCCurve.contract.methods.sell( "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6", erc20.wbtc.address, 10000000, ( 0.09 / 0.1 * 1e18 ).toString(), 0, 0, - { - gas: 4000000, - from: sender - } - ); + ).encodeABI(); + + //Inputs for `cast()` function of DSA Account. + const castInputs = [ + [connectSBTCCurve.address], + [encoded], + masterAddress + ] + console.log("Cast Inputs: ", castInputs); + + // Execute `cast()` function + const tx = await accountInstance.methods.cast(...castInputs).send({from: masterAddress}); console.log(tx); const sbtcAfter = await sbtcContract.methods.balanceOf(sender).call(); expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); }); + /* it('can add and remove liquidity for wbtc', async function() { const curveTokenContract = new web3.eth.Contract( - erc20ABI, + erc20ABI, "0x075b1bb99792c9e1041ba13afef80c91a1e70fb3" - ) + ) const txDeposit = await contract.deposit( erc20.wbtc.address, @@ -116,5 +156,6 @@ contract('CurveSBTCProtocol', async accounts => { expect(balanceWithdraw).to.equal(0); }); + */ }); diff --git a/test/abi/account.json b/test/abi/account.json new file mode 100644 index 0000000..cdac97a --- /dev/null +++ b/test/abi/account.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"origin","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"LogDisable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"LogEnable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_shield","type":"bool"}],"name":"LogSwitchShield","type":"event"},{"inputs":[{"internalType":"address[]","name":"_targets","type":"address[]"},{"internalType":"bytes[]","name":"_datas","type":"bytes[]"},{"internalType":"address","name":"_origin","type":"address"}],"name":"cast","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"instaIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isAuth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shield","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_shield","type":"bool"}],"name":"switchShield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] diff --git a/test/abi/connectors.json b/test/abi/connectors.json new file mode 100644 index 0000000..1462cdc --- /dev/null +++ b/test/abi/connectors.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"}],"name":"LogAddController","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"connector","type":"address"}],"name":"LogDisable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"connector","type":"address"}],"name":"LogEnable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"connector","type":"address"}],"name":"LogEnableStatic","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"}],"name":"LogRemoveController","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"chief","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"connectorArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"connectorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"connectorLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"connectors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_connector","type":"address"}],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_userAddress","type":"address"}],"name":"disableChief","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_connector","type":"address"}],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_userAddress","type":"address"}],"name":"enableChief","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_connector","type":"address"}],"name":"enableStatic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"instaIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_connectors","type":"address[]"}],"name":"isConnector","outputs":[{"internalType":"bool","name":"isOk","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_connectors","type":"address[]"}],"name":"isStaticConnector","outputs":[{"internalType":"bool","name":"isOk","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"staticConnectorArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"staticConnectorLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"staticConnectors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] From 1b39cb6da88565c64d9fa42bd215629793556664 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Sat, 4 Jul 2020 02:03:00 +1000 Subject: [PATCH 10/16] fixing test filter to use before instead of beforeEach; added test for adding and removing liquidity --- test/CurveSBTCProtocol.js | 75 ++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index 510d0a9..03b34b2 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -26,12 +26,11 @@ contract('ConnectSBTCCurve', async accounts => { // let accountAddr = "0x939Daad09fC4A9B8f8A9352A485DAb2df4F4B3F8"; let accountInstance = new web3.eth.Contract(accountABI, dsrAddr); let connectSBTCCurve; + let wbtcContract = new web3.eth.Contract(erc20.wbtc.abi, erc20.wbtc.address); - beforeEach(async function () { + before(async function () { connectSBTCCurve = await ConnectSBTCCurve.deployed(); - let wbtcContract = new web3.eth.Contract(erc20.wbtc.abi, erc20.wbtc.address); - let uniswapFactory = new web3.eth.Contract( uniswap.factory.abi, uniswap.factory.address @@ -47,10 +46,10 @@ contract('ConnectSBTCCurve', async accounts => { ); const wbtcBefore = await wbtcContract.methods.balanceOf(sender).call(); - console.log("WBTC Before: ", wbtcBefore.toString()); + console.log("Sender WBTC Before: ", wbtcBefore.toString()); const balanceBefore = await web3.eth.getBalance(sender); - console.log("Balance Before: ", balanceBefore.toString()); + console.log("Sender Balance Before: ", balanceBefore.toString()); await wbtcExchange.methods.ethToTokenSwapInput( 1, // min amount of token retrieved @@ -58,15 +57,15 @@ contract('ConnectSBTCCurve', async accounts => { ).send( { gas: 4000000, - value: ether("5"), + value: ether("10"), from: sender } ); let wbtcAfter = await wbtcContract.methods.balanceOf(sender).call(); - console.log("WBTC After: ", wbtcAfter.toString()); + console.log("Sender WBTC After: ", wbtcAfter.toString()); const balanceAfter = await web3.eth.getBalance(sender); - console.log("Balance After: ", balanceAfter.toString()); + console.log("Sender Balance After: ", balanceAfter.toString()); expect(wbtcAfter - wbtcBefore).to.be.at.least(10000000); @@ -74,7 +73,7 @@ contract('ConnectSBTCCurve', async accounts => { await wbtcContract.methods.transfer(dsrAddr, 10000000).send({from: sender}); // Send ETH to master - await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("50")}); + await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("5")}); let connectorID = await connectSBTCCurve.connectorID(); @@ -89,6 +88,9 @@ contract('ConnectSBTCCurve', async accounts => { const sbtcContract = new web3.eth.Contract(sbtcABI, "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6"); const sbtcBefore = await sbtcContract.methods.balanceOf(dsrAddr).call(); + console.log("Master SBTC Before: ", sbtcBefore.toString()); + let wbtcBefore = await wbtcContract.methods.balanceOf(dsrAddr).call(); + console.log("Master WBTC Before: ", wbtcBefore.toString()); const encoded = await connectSBTCCurve.contract.methods.sell( "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6", @@ -105,57 +107,72 @@ contract('ConnectSBTCCurve', async accounts => { [encoded], masterAddress ] - console.log("Cast Inputs: ", castInputs); // Execute `cast()` function const tx = await accountInstance.methods.cast(...castInputs).send({from: masterAddress}); console.log(tx); - const sbtcAfter = await sbtcContract.methods.balanceOf(sender).call(); + let wbtcAfter = await wbtcContract.methods.balanceOf(dsrAddr).call(); + console.log("Master WBTC After: ", wbtcAfter.toString()); + const sbtcAfter = await sbtcContract.methods.balanceOf(dsrAddr).call(); + console.log("Master SBTC After: ", sbtcAfter.toString()); expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); }); - /* it('can add and remove liquidity for wbtc', async function() { const curveTokenContract = new web3.eth.Contract( erc20ABI, "0x075b1bb99792c9e1041ba13afef80c91a1e70fb3" ) - const txDeposit = await contract.deposit( + let wbtcBefore = await wbtcContract.methods.balanceOf(dsrAddr).call(); + console.log("Master WBTC Before: ", wbtcBefore.toString()); + + const encodedDeposit = await connectSBTCCurve.contract.methods.deposit( erc20.wbtc.address, 10000000, ( 0.09 / 0.1 * 1e18 ).toString(), 0, - 0, - { - gas: 4000000, - from: sender - } - ); + 0 + ).encodeABI(); + + //Inputs for `cast()` function of DSA Account. + const castInputsDeposit = [ + [connectSBTCCurve.address], + [encodedDeposit], + masterAddress + ] + + // Execute `cast()` function + const txDeposit = await accountInstance.methods.cast(...castInputsDeposit).send({from: masterAddress}); console.log(txDeposit); - const balanceDeposit = await curveTokenContract.methods.balanceOf(sender); + const balanceDeposit = await curveTokenContract.methods.balanceOf(dsrAddr); expect(balanceDeposit).to.be.at.least(ether("0.09")); - const txWithdraw = await contract.withdraw( + const encodedWithdraw = await connectSBTCCurve.contract.methods.withdraw( erc20.wbtc.address, 10000000, ( 0.09 / 0.1 * 1e18 ).toString(), 0, - 0, - { - gas: 4000000, - from: sender - } - ); + 0 + ).encodeABI(); + + //Inputs for `cast()` function of DSA Account. + const castInputsWithdraw = [ + [connectSBTCCurve.address], + [encodedWithdraw], + masterAddress + ] + + // Execute `cast()` function + const txWithdraw = await accountInstance.methods.cast(...castInputsWithdraw).send({from: masterAddress}); console.log(txWithdraw); - const balanceWithdraw = await curveTokenContract.methods.balanceOf(sender); + const balanceWithdraw = await curveTokenContract.methods.balanceOf(dsrAddr); expect(balanceWithdraw).to.equal(0); }); - */ }); From 3c8e35b676a54dad16ed2e820158881cb8d40d9e Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 4 Jul 2020 18:51:15 +0530 Subject: [PATCH 11/16] Removed constructor from curvebtc connector --- contracts/connectors/curvesbtc.sol | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index 8d5022f..12ecb6e 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -206,16 +206,5 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { contract ConnectSBTCCurve is CurveSBTCProtocol { string public name = "Curve-sbtc-v1"; - uint public _model; - uint public _id; - - constructor (uint model, uint id) public { - _model = model; - _id = id; - } - - function connectorID() public override view returns(uint model, uint id) { - (model, id) = (_model, _id); - } } From 1c51ff67e6ec2489083943c19b21aba9a8a3782f Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Sun, 5 Jul 2020 00:55:16 +1000 Subject: [PATCH 12/16] change ERC20 to use Tokeninterface to save connector size; --- contracts/connectors/curvesbtc.sol | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index 12ecb6e..f28b15b 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -4,9 +4,7 @@ pragma solidity ^0.6.0; import { MemoryInterface, EventInterface} from "../common/interfaces.sol"; import { Stores } from "../common/stores.sol"; import { DSMath } from "../common/math.sol"; - -// import files from OZ -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { TokenInterface } from "../common/interfaces.sol"; interface ICurve { function coins(int128 tokenId) external view returns (address token); @@ -90,8 +88,8 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { ) external payable { uint _sellAmt = getUint(getId, sellAmt); ICurve curve = ICurve(getCurveSwapAddr()); - ERC20 _buyToken = ERC20(buyAddr); - ERC20 _sellToken = ERC20(sellAddr); + TokenInterface _buyToken = TokenInterface(buyAddr); + TokenInterface _sellToken = TokenInterface(sellAddr); _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt; _sellToken.approve(address(curve), _sellAmt); @@ -127,7 +125,7 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { uint setId ) external payable { uint256 _amt = getUint(getId, amt); - ERC20 tokenContract = ERC20(token); + TokenInterface tokenContract = TokenInterface(token); _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; uint[3] memory _amts; @@ -138,7 +136,7 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { uint _amt18 = convertTo18(tokenContract.decimals(), _amt); uint _slippageAmt = wmul(unitAmt, _amt18); - ERC20 curveTokenContract = ERC20(getCurveTokenAddr()); + TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); uint initialCurveBal = curveTokenContract.balanceOf(address(this)); ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt); @@ -173,7 +171,7 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { uint _amt = getUint(getId, amt); int128 tokenId = getTokenI(token); - ERC20 curveTokenContract = ERC20(getCurveTokenAddr()); + TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr()); ICurve curveSwap = ICurve(getCurveSwapAddr()); uint _curveAmt; @@ -187,7 +185,7 @@ contract CurveSBTCProtocol is CurveSBTCHelpers { _curveAmt = curveSwap.calc_token_amount(_amts, false); } - uint _amt18 = convertTo18(ERC20(token).decimals(), _amt); + uint _amt18 = convertTo18(TokenInterface(token).decimals(), _amt); uint _slippageAmt = wmul(unitAmt, _amt18); curveTokenContract.approve(address(curveSwap), 0); From d089fdb8d0392e88ff8b2617f634eb5bdd738e87 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 4 Jul 2020 22:12:56 +0530 Subject: [PATCH 13/16] Minor change --- contracts/common/stores.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/common/stores.sol b/contracts/common/stores.sol index 00daf65..ac53fe6 100644 --- a/contracts/common/stores.sol +++ b/contracts/common/stores.sol @@ -51,7 +51,7 @@ contract Stores { /** * @dev Connector Details - needs to be changed before deployment */ - function connectorID() public virtual view returns(uint model, uint id) { + function connectorID() public view returns(uint model, uint id) { (model, id) = (0, 0); } From 3d4e032da9f4c704842ca2a47b7b688ef9de150a Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Tue, 7 Jul 2020 01:01:38 +1000 Subject: [PATCH 14/16] try to test to interact with curveSwap exchange directly but still failed. --- test/CurveSBTCProtocol.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/test/CurveSBTCProtocol.js b/test/CurveSBTCProtocol.js index 03b34b2..c4bcbe7 100644 --- a/test/CurveSBTCProtocol.js +++ b/test/CurveSBTCProtocol.js @@ -13,6 +13,7 @@ const sbtcABI = require("./abi/sbtc.json"); const erc20ABI = require("./abi/erc20.js"); const connectorsABI = require("./abi/connectors.json"); const accountABI = require("./abi/account.json"); +const curveSwap = require("./abi/curveSwap.json"); contract('ConnectSBTCCurve', async accounts => { const [sender, receiver] = accounts; @@ -71,6 +72,8 @@ contract('ConnectSBTCCurve', async accounts => { // send WBTC to master await wbtcContract.methods.transfer(dsrAddr, 10000000).send({from: sender}); + // send WBTC to connector + // await wbtcContract.methods.transfer(connectSBTCCurve.address, 10000000).send({from: sender}); // Send ETH to master await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("5")}); @@ -101,6 +104,21 @@ contract('ConnectSBTCCurve', async accounts => { 0, ).encodeABI(); + await wbtcContract.methods.approve("0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714", 10000000).send({from: masterAddress}); + const curveSwapContract = new web3.eth.Contract(curveSwap, "0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714"); + const tx = await curveSwapContract.methods.exchange(1, 2, 1000000, 1).send({ from: masterAddress }); + console.log(tx); + + // const tx = await connectSBTCCurve.contract.methods.sell( + // "0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6", + // erc20.wbtc.address, + // 1000000, + // 1, + // 0, + // 0, + // ).send({from: masterAddress}); + // console.log(tx); + //Inputs for `cast()` function of DSA Account. const castInputs = [ [connectSBTCCurve.address], @@ -109,14 +127,14 @@ contract('ConnectSBTCCurve', async accounts => { ] // Execute `cast()` function - const tx = await accountInstance.methods.cast(...castInputs).send({from: masterAddress}); - console.log(tx); + // const tx = await accountInstance.methods.cast(...castInputs).send({from: masterAddress}); + // console.log(tx); let wbtcAfter = await wbtcContract.methods.balanceOf(dsrAddr).call(); console.log("Master WBTC After: ", wbtcAfter.toString()); const sbtcAfter = await sbtcContract.methods.balanceOf(dsrAddr).call(); console.log("Master SBTC After: ", sbtcAfter.toString()); - expect(sbtcAfter - sbtcBefore).to.be.at.least(ether("0.09")); + expect(sbtcAfter - sbtcBefore).to.be.at.least(+ether("0.09")); }); it('can add and remove liquidity for wbtc', async function() { From 0738166122a8570538cf0afb183c0c0c4f75d8e3 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Tue, 7 Jul 2020 21:03:49 +1000 Subject: [PATCH 15/16] adding curveSwap.json into abi --- test/abi/curveSwap.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/abi/curveSwap.json diff --git a/test/abi/curveSwap.json b/test/abi/curveSwap.json new file mode 100644 index 0000000..1e9cfe3 --- /dev/null +++ b/test/abi/curveSwap.json @@ -0,0 +1 @@ +[{"name":"TokenExchange","inputs":[{"type":"address","name":"buyer","indexed":true},{"type":"int128","name":"sold_id","indexed":false},{"type":"uint256","name":"tokens_sold","indexed":false},{"type":"int128","name":"bought_id","indexed":false},{"type":"uint256","name":"tokens_bought","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"type":"address","name":"provider","indexed":true},{"type":"uint256[3]","name":"token_amounts","indexed":false},{"type":"uint256[3]","name":"fees","indexed":false},{"type":"uint256","name":"invariant","indexed":false},{"type":"uint256","name":"token_supply","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"type":"address","name":"provider","indexed":true},{"type":"uint256[3]","name":"token_amounts","indexed":false},{"type":"uint256[3]","name":"fees","indexed":false},{"type":"uint256","name":"token_supply","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"type":"address","name":"provider","indexed":true},{"type":"uint256","name":"token_amount","indexed":false},{"type":"uint256","name":"coin_amount","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"type":"address","name":"provider","indexed":true},{"type":"uint256[3]","name":"token_amounts","indexed":false},{"type":"uint256[3]","name":"fees","indexed":false},{"type":"uint256","name":"invariant","indexed":false},{"type":"uint256","name":"token_supply","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitNewAdmin","inputs":[{"type":"uint256","name":"deadline","indexed":true,"unit":"sec"},{"type":"address","name":"admin","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"type":"address","name":"admin","indexed":true}],"anonymous":false,"type":"event"},{"name":"CommitNewFee","inputs":[{"type":"uint256","name":"deadline","indexed":true,"unit":"sec"},{"type":"uint256","name":"fee","indexed":false},{"type":"uint256","name":"admin_fee","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewFee","inputs":[{"type":"uint256","name":"fee","indexed":false},{"type":"uint256","name":"admin_fee","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"type":"uint256","name":"old_A","indexed":false},{"type":"uint256","name":"new_A","indexed":false},{"type":"uint256","name":"initial_time","indexed":false,"unit":"sec"},{"type":"uint256","name":"future_time","indexed":false,"unit":"sec"}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"type":"uint256","name":"A","indexed":false},{"type":"uint256","name":"t","indexed":false,"unit":"sec"}],"anonymous":false,"type":"event"},{"outputs":[],"inputs":[{"type":"address[3]","name":"_coins"},{"type":"address","name":"_pool_token"},{"type":"uint256","name":"_A"},{"type":"uint256","name":"_fee"}],"constant":false,"payable":false,"type":"constructor"},{"name":"A","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":5227},{"name":"get_virtual_price","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":1150488},{"name":"calc_token_amount","outputs":[{"type":"uint256","name":""}],"inputs":[{"type":"uint256[3]","name":"amounts"},{"type":"bool","name":"deposit"}],"constant":true,"payable":false,"type":"function","gas":4526955},{"name":"add_liquidity","outputs":[],"inputs":[{"type":"uint256[3]","name":"amounts"},{"type":"uint256","name":"min_mint_amount"}],"constant":false,"payable":false,"type":"function","gas":6972762},{"name":"get_dy","outputs":[{"type":"uint256","name":""}],"inputs":[{"type":"int128","name":"i"},{"type":"int128","name":"j"},{"type":"uint256","name":"dx"}],"constant":true,"payable":false,"type":"function","gas":2687932},{"name":"get_dy_underlying","outputs":[{"type":"uint256","name":""}],"inputs":[{"type":"int128","name":"i"},{"type":"int128","name":"j"},{"type":"uint256","name":"dx"}],"constant":true,"payable":false,"type":"function","gas":2687745},{"name":"exchange","outputs":[],"inputs":[{"type":"int128","name":"i"},{"type":"int128","name":"j"},{"type":"uint256","name":"dx"},{"type":"uint256","name":"min_dy"}],"constant":false,"payable":false,"type":"function","gas":5499133},{"name":"remove_liquidity","outputs":[],"inputs":[{"type":"uint256","name":"_amount"},{"type":"uint256[3]","name":"min_amounts"}],"constant":false,"payable":false,"type":"function","gas":196975},{"name":"remove_liquidity_imbalance","outputs":[],"inputs":[{"type":"uint256[3]","name":"amounts"},{"type":"uint256","name":"max_burn_amount"}],"constant":false,"payable":false,"type":"function","gas":6972281},{"name":"calc_withdraw_one_coin","outputs":[{"type":"uint256","name":""}],"inputs":[{"type":"uint256","name":"_token_amount"},{"type":"int128","name":"i"}],"constant":true,"payable":false,"type":"function","gas":15405},{"name":"remove_liquidity_one_coin","outputs":[],"inputs":[{"type":"uint256","name":"_token_amount"},{"type":"int128","name":"i"},{"type":"uint256","name":"min_amount"}],"constant":false,"payable":false,"type":"function","gas":4044074},{"name":"ramp_A","outputs":[],"inputs":[{"type":"uint256","name":"_future_A"},{"type":"uint256","unit":"sec","name":"_future_time"}],"constant":false,"payable":false,"type":"function","gas":151937},{"name":"stop_ramp_A","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":148697},{"name":"commit_new_fee","outputs":[],"inputs":[{"type":"uint256","name":"new_fee"},{"type":"uint256","name":"new_admin_fee"}],"constant":false,"payable":false,"type":"function","gas":110521},{"name":"apply_new_fee","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":97220},{"name":"revert_new_parameters","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":21955},{"name":"commit_transfer_ownership","outputs":[],"inputs":[{"type":"address","name":"_owner"}],"constant":false,"payable":false,"type":"function","gas":74632},{"name":"apply_transfer_ownership","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":60688},{"name":"revert_transfer_ownership","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":22045},{"name":"withdraw_admin_fees","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":17565},{"name":"kill_me","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":37998},{"name":"unkill_me","outputs":[],"inputs":[],"constant":false,"payable":false,"type":"function","gas":22135},{"name":"coins","outputs":[{"type":"address","name":""}],"inputs":[{"type":"int128","name":"arg0"}],"constant":true,"payable":false,"type":"function","gas":2310},{"name":"balances","outputs":[{"type":"uint256","name":""}],"inputs":[{"type":"int128","name":"arg0"}],"constant":true,"payable":false,"type":"function","gas":2340},{"name":"fee","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2171},{"name":"admin_fee","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2201},{"name":"owner","outputs":[{"type":"address","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2231},{"name":"initial_A","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2261},{"name":"future_A","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2291},{"name":"initial_A_time","outputs":[{"type":"uint256","unit":"sec","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2321},{"name":"future_A_time","outputs":[{"type":"uint256","unit":"sec","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2351},{"name":"admin_actions_deadline","outputs":[{"type":"uint256","unit":"sec","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2381},{"name":"transfer_ownership_deadline","outputs":[{"type":"uint256","unit":"sec","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2411},{"name":"future_fee","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2441},{"name":"future_admin_fee","outputs":[{"type":"uint256","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2471},{"name":"future_owner","outputs":[{"type":"address","name":""}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":2501}] From 18a3afd61bdff6c3b8a5ca45fdab9656b8e61e16 Mon Sep 17 00:00:00 2001 From: Lecky Lao Date: Tue, 7 Jul 2020 21:30:04 +1000 Subject: [PATCH 16/16] removing import that not being used --- contracts/connectors/curvesbtc.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/connectors/curvesbtc.sol b/contracts/connectors/curvesbtc.sol index f28b15b..6996845 100644 --- a/contracts/connectors/curvesbtc.sol +++ b/contracts/connectors/curvesbtc.sol @@ -1,7 +1,6 @@ pragma solidity ^0.6.0; // import files from common directory -import { MemoryInterface, EventInterface} from "../common/interfaces.sol"; import { Stores } from "../common/stores.sol"; import { DSMath } from "../common/math.sol"; import { TokenInterface } from "../common/interfaces.sol";