From a0d936ddfb72a3dee2518204e4f34cae35acf576 Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 21:44:05 +0100 Subject: [PATCH 01/10] refactoring and reorganizing some code --- contracts/Treasurer.sol | 55 +- contracts/{ => imports}/Imports.sol | 0 .../UniswapExchangeInterface.sol | 0 .../UniswapFactoryInterface.sol | 0 contracts/{ => oracle}/Oracle.sol | 1 - .../uniswapexchangemock.sol | 2 +- .../uniswapfactorymock.sol | 0 package-lock.json | 3511 ++++++++++++++++- package.json | 4 +- 9 files changed, 3374 insertions(+), 199 deletions(-) rename contracts/{ => imports}/Imports.sol (100%) rename contracts/{ => interfaces}/UniswapExchangeInterface.sol (100%) rename contracts/{ => interfaces}/UniswapFactoryInterface.sol (100%) rename contracts/{ => oracle}/Oracle.sol (91%) rename contracts/{ => test-contracts}/uniswapexchangemock.sol (84%) rename contracts/{ => test-contracts}/uniswapfactorymock.sol (100%) diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 9814a75..6a93313 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -1,12 +1,13 @@ pragma solidity ^0.5.2; -pragma experimental ABIEncoderV2; import './yToken.sol'; -import './Oracle.sol'; - +import './oracle/Oracle.sol'; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract Treasurer { + using SafeMath for uint256; + struct Repo { uint256 locked; // Locked Collateral uint256 unminted; // unminted @@ -38,25 +39,13 @@ contract Treasurer { // --- Math --- uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; - function add(uint x, uint y) internal pure returns (uint z) { - z = x + y; - require(z >= x, "treasurer-add-z-not-greater-eq-x"); - } - - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, "treasurer-sub-failed"); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, "treasurer-mul-failed"); - } function wmul(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, y), WAD / 2) / WAD; + z = x.mul(y).add(WAD / 2) / WAD; } function wdiv(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, WAD), y / 2) / y; + z = x.mul(WAD).add(y / 2) / y; } // --- Views --- @@ -98,7 +87,7 @@ contract Treasurer { // add collateral to repo function join() external payable { require(msg.value >= 0, "treasurer-join-collateralRatio-include-deposit"); - unlocked[msg.sender] = add(unlocked[msg.sender], msg.value); + unlocked[msg.sender] = unlocked[msg.sender].add(msg.value); } // remove collateral from repo @@ -106,7 +95,7 @@ contract Treasurer { // TO-DO: Update as described in https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ function exit(uint amount) external { require(amount >= 0, "treasurer-exit-insufficient-balance"); - unlocked[msg.sender] = sub(unlocked[msg.sender], amount); + unlocked[msg.sender] = unlocked[msg.sender].sub(amount); msg.sender.transfer(amount); } @@ -125,9 +114,9 @@ contract Treasurer { require (paid >= min, "treasurer-make-insufficient-collateral-for-those-tokens"); // lock msg.sender Collateral, add debt - unlocked[msg.sender] = sub(unlocked[msg.sender], paid); - repo.locked = add(repo.locked, paid); - repo.debt = add(repo.debt, made); + unlocked[msg.sender] = unlocked[msg.sender].sub(paid); + repo.locked = repo.locked.add(paid); + repo.debt = repo.debt.add(made); repos[series][msg.sender] = repo; // mint new yTokens @@ -150,13 +139,13 @@ contract Treasurer { require(repo.locked >= released, "treasurer-wipe-release-more-than-locked"); require(repo.debt >= credit, "treasurer-wipe-wipe-more-debt-than-present"); // if would be undercollateralized after freeing clean, fail - uint rlocked = sub(repo.locked, released); - uint rdebt = sub(repo.debt, credit); + uint rlocked = repo.locked.sub(released); + uint rdebt = repo.debt.sub(credit); uint rate = peek(); // to add rate getter!!! uint256 min = wmul(wmul(rdebt, collateralRatio), rate); uint deficiency = 0; if (min >= rlocked){ - deficiency = sub(min, rlocked); + deficiency = min.sub(rlocked); } return (rlocked >= min, deficiency); } @@ -174,8 +163,8 @@ contract Treasurer { require(repo.locked >= released, "treasurer-wipe-release-more-than-locked"); require(repo.debt >= credit, "treasurer-wipe-wipe-more-debt-than-present"); // if would be undercollateralized after freeing clean, fail - uint rlocked = sub(repo.locked, released); - uint rdebt = sub(repo.debt, credit); + uint rlocked = repo.locked.sub(released); + uint rdebt = repo.debt.sub(credit); uint rate = peek(); // to add rate getter!!! uint256 min = wmul(wmul(rdebt, collateralRatio), rate); require(rlocked >= min, "treasurer-wipe-insufficient-remaining-collateral"); @@ -186,12 +175,12 @@ contract Treasurer { yT.burnFrom(msg.sender, credit); // reduce the collateral and the debt - repo.locked = sub(repo.locked, released); - repo.debt = sub(repo.debt, credit); + repo.locked = repo.locked.sub(released); + repo.debt = repo.debt.sub(credit); repos[series][msg.sender] = repo; // add collateral back to the unlocked - unlocked[msg.sender] = add(unlocked[msg.sender], released); + unlocked[msg.sender] = unlocked[msg.sender].add(released); } // liquidate a repo @@ -212,8 +201,8 @@ contract Treasurer { //update repo uint256 bitten = wmul(wmul(amount, minCollateralRatio), rate); - repo.locked = sub(repo.locked, bitten); - repo.debt = sub(repo.debt, amount); + repo.locked = repo.locked.sub(bitten); + repo.debt = repo.debt.sub(amount); repos[series][bum] = repo; // send bitten funds @@ -258,7 +247,7 @@ contract Treasurer { uint remainder = wmul(repo.debt, rate); require(repo.locked > remainder, "treasurer-settlement-repo-underfunded-at-settlement" ); - uint256 goods = sub(repo.locked, wmul(repo.debt, rate)); + uint256 goods = repo.locked.sub(wmul(repo.debt, rate)); repo.locked = 0; repo.debt = 0; repos[series][msg.sender] = repo; diff --git a/contracts/Imports.sol b/contracts/imports/Imports.sol similarity index 100% rename from contracts/Imports.sol rename to contracts/imports/Imports.sol diff --git a/contracts/UniswapExchangeInterface.sol b/contracts/interfaces/UniswapExchangeInterface.sol similarity index 100% rename from contracts/UniswapExchangeInterface.sol rename to contracts/interfaces/UniswapExchangeInterface.sol diff --git a/contracts/UniswapFactoryInterface.sol b/contracts/interfaces/UniswapFactoryInterface.sol similarity index 100% rename from contracts/UniswapFactoryInterface.sol rename to contracts/interfaces/UniswapFactoryInterface.sol diff --git a/contracts/Oracle.sol b/contracts/oracle/Oracle.sol similarity index 91% rename from contracts/Oracle.sol rename to contracts/oracle/Oracle.sol index a5cb55e..af05ede 100644 --- a/contracts/Oracle.sol +++ b/contracts/oracle/Oracle.sol @@ -1,5 +1,4 @@ pragma solidity ^0.5.2; -pragma experimental ABIEncoderV2; //Using fake contract instead of abstract for mocking contract Oracle { diff --git a/contracts/uniswapexchangemock.sol b/contracts/test-contracts/uniswapexchangemock.sol similarity index 84% rename from contracts/uniswapexchangemock.sol rename to contracts/test-contracts/uniswapexchangemock.sol index 70c8367..43a6300 100644 --- a/contracts/uniswapexchangemock.sol +++ b/contracts/test-contracts/uniswapexchangemock.sol @@ -3,7 +3,7 @@ pragma solidity ^0.5.2; contract UniswapExchangeMock { - function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought){ + function getEthToTokenInputPrice(uint256 eth_sold) external pure returns (uint256 tokens_bought){ return 0.98 ether + (eth_sold - eth_sold); } diff --git a/contracts/uniswapfactorymock.sol b/contracts/test-contracts/uniswapfactorymock.sol similarity index 100% rename from contracts/uniswapfactorymock.sol rename to contracts/test-contracts/uniswapfactorymock.sol diff --git a/package-lock.json b/package-lock.json index 801cbc8..e59c712 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,15 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/runtime": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", + "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, "@gnosis.pm/mock-contract": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@gnosis.pm/mock-contract/-/mock-contract-3.0.7.tgz", @@ -26,11 +35,36 @@ "defer-to-connect": "^1.0.1" } }, + "@types/bn.js": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.5.tgz", + "integrity": "sha512-AEAZcIZga0JgVMHNtl1CprA/hXX7/wPt79AgR4XqaDt7jyj3QWYw6LPoOiznPtugDmlubUnAahMs2PFxGcQrng==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "10.14.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.22.tgz", "integrity": "sha512-9taxKC944BqoTVjE+UT3pQH0nHZlTvITwfsOZqyc+R3sfJuxaTtxWjfn1K2UlxyPcKHf0rnaXcVFrS9F9vf0bw==" }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -45,6 +79,24 @@ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -56,11 +108,63 @@ "uri-js": "^4.2.2" } }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -94,6 +198,12 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -114,6 +224,12 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -180,11 +296,43 @@ "type-is": "~1.6.17" } }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -284,6 +432,12 @@ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", @@ -294,11 +448,56 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -328,16 +527,62 @@ } } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "chownr": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", + "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -347,6 +592,21 @@ "safe-buffer": "^5.0.1" } }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -355,6 +615,27 @@ "mimic-response": "^1.0.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==", + "dev": true, + "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=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -371,6 +652,38 @@ "graceful-readlink": ">= 1.0.0" } }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -406,6 +719,20 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -454,6 +781,35 @@ "sha.js": "^2.4.8" } }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -472,14 +828,17 @@ "randomfill": "^1.0.3" } }, - "d": { + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "cyclist": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true }, "dashdash": { "version": "1.14.1", @@ -489,6 +848,12 @@ "assert-plus": "^1.0.0" } }, + "death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -591,6 +956,18 @@ } } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "defer-to-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", @@ -628,6 +1005,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -643,6 +1026,15 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, "dotenv": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.1.0.tgz", @@ -664,6 +1056,18 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -692,11 +1096,26 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -705,6 +1124,12 @@ "once": "^1.4.0" } }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, "es-abstract": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", @@ -732,33 +1157,19 @@ "is-symbol": "^1.0.2" } }, - "es5-ext": { - "version": "0.10.51", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz", - "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true }, - "es6-symbol": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz", - "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==", + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.51" + "es6-promise": "^4.0.3" } }, "escape-html": { @@ -766,6 +1177,43 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "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 + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -811,87 +1259,826 @@ "ethereumjs-util": "^6.0.0" } }, - "ethereumjs-util": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", - "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "ethereumjs-testrpc-sc": { + "version": "6.5.1-sc.1", + "resolved": "https://registry.npmjs.org/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.5.1-sc.1.tgz", + "integrity": "sha512-DPBwpMFFH5DTXicYjLLdTq6VLnD8p4oo5QfC9EmRKLzDsWRNXDhA9cgcdUZhhXuPM+mVAem7Q+o3Y3CQ5f+FKA==", "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" - } - }, - "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" + "ethereumjs-util": "6.1.0", + "source-map-support": "0.5.12", + "yargs": "13.2.4" }, "dependencies": { - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" + "color-convert": "^1.9.0" } }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "bindings": { + "version": "1.5.0", + "bundled": true, + "dev": true, "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" + "file-uri-to-path": "1.0.0" } }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "bip66": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } }, - "setimmediate": { + "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 + }, + "cipher-base": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" - } - } - }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "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" + } + }, + "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" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "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.1", + "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-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" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "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.1", + "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 + }, + "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.1", + "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": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.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 + }, + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "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" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "bundled": true, + "dev": true + } + } + } + } + }, + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" } } @@ -920,6 +2107,29 @@ "safe-buffer": "^5.1.1" } }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -979,11 +2189,23 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -992,6 +2214,12 @@ "pend": "~1.2.0" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", @@ -1016,6 +2244,26 @@ "unpipe": "~1.0.0" } }, + "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" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -1049,6 +2297,16 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1072,6 +2330,24 @@ "minipass": "^2.6.0" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1082,6 +2358,18 @@ "resolved": "https://registry.npmjs.org/ganache-time-traveler/-/ganache-time-traveler-1.0.5.tgz", "integrity": "sha512-46lhryBbHfNyixWq22zgK5OeRF4T8FgA67idiKMwYAePAvj1gqREaljVO2aV5GBouovtp8jg8qt+TXTXTtUEsQ==" }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -1098,6 +2386,19 @@ "assert-plus": "^1.0.0" } }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -1107,6 +2408,15 @@ "process": "~0.5.1" } }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -1135,6 +2445,32 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "handlebars": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1157,6 +2493,21 @@ "function-bind": "^1.1.1" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", @@ -1175,6 +2526,12 @@ "has-symbol-support-x": "^1.4.1" } }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -1193,6 +2550,12 @@ "minimalistic-assert": "^1.0.1" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -1203,6 +2566,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "dev": true + }, "http-cache-semantics": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", @@ -1232,6 +2601,27 @@ "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1242,6 +2632,42 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "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==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1265,16 +2691,77 @@ } } }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -1285,11 +2772,26 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, "is-function": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", @@ -1300,16 +2802,47 @@ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, "is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" }, + "is-npm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", + "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -1346,16 +2879,50 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + } + }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", @@ -1365,11 +2932,35 @@ "is-object": "^1.0.1" } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, "js-sha3": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -1380,6 +2971,21 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "dev": true, + "requires": { + "jju": "^1.1.0" + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -1395,6 +3001,23 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -1403,6 +3026,12 @@ "graceful-fs": "^4.1.6" } }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1443,6 +3072,93 @@ "json-buffer": "3.0.0" } }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "libnpmconfig": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "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 + } + } + }, + "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" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -1453,6 +3169,15 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -1468,6 +3193,33 @@ } } }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + }, + "dependencies": { + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -1543,6 +3295,15 @@ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", @@ -1557,64 +3318,375 @@ "yallist": "^3.0.0" } }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "requires": { + "mkdirp": "*" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "mock-fs": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.10.2.tgz", + "integrity": "sha512-ewPQ83O4U8/Gd8I15WoB6vgTTmq5khxBskUWCRvswUqjCfOOTREmxllztQOm+PXMWUxATry+VBWXQJloAyxtbQ==" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nested-error-stacks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", + "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", + "dev": true + }, + "node-alias": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-alias/-/node-alias-1.0.4.tgz", + "integrity": "sha1-HxuRa1a56iQcATX5fO1pQPVW8pI=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "lodash": "^4.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "node-fetch-npm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", + "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz", + "integrity": "sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + }, + "npm-bundled": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "dev": true + }, + "npm-check-updates": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-3.2.1.tgz", + "integrity": "sha512-gYXHGc9mAncGrEMjs2uRJgOdWRP5CR9iZ+HyUNf4eqjtdDV6jLvi2e19G5BEpdvc8fU73J+B5m8ALYB49du/EA==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cint": "^8.2.1", + "cli-table": "^0.3.1", + "commander": "^3.0.2", + "fast-diff": "^1.2.0", + "find-up": "4.1.0", + "get-stdin": "^7.0.0", + "json-parse-helpfulerror": "^1.0.3", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.15", + "node-alias": "^1.0.4", + "pacote": "^9.5.8", + "progress": "^2.0.3", + "prompts": "^2.2.1", + "rc-config-loader": "^2.0.4", + "requireg": "^0.2.2", + "semver": "^6.3.0", + "semver-utils": "^1.1.4", + "spawn-please": "^0.3.0", + "update-notifier": "^3.0.1" + }, + "dependencies": { + "commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, "requires": { - "minipass": "^2.9.0" + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "npm-packlist": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz", + "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==", + "dev": true, "requires": { - "minimist": "0.0.8" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, - "mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, "requires": { - "mkdirp": "*" + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "mock-fs": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.10.2.tgz", - "integrity": "sha512-ewPQ83O4U8/Gd8I15WoB6vgTTmq5khxBskUWCRvswUqjCfOOTREmxllztQOm+PXMWUxATry+VBWXQJloAyxtbQ==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" - }, - "nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "npm-registry-fetch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz", + "integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + } }, - "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } }, "number-to-bn": { "version": "1.7.0", @@ -1681,6 +3753,66 @@ "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-2.3.0.tgz", "integrity": "sha512-QYeiPLvB1oSbDt6lDQvvpx7k8ODczvE474hb2kLXZBPKMsxKT1WxTCHBYrCU7kS7hfAku4DcJ0jqOyL+jvjwQw==" }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "original-require": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -1691,6 +3823,24 @@ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "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-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", @@ -1699,6 +3849,94 @@ "p-finally": "^1.0.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 + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, + "pacote": { + "version": "9.5.9", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.9.tgz", + "integrity": "sha512-S1nYW9ly+3btn3VmwRAk2LG3TEh8mkrFdY+psbnHSk8oPODbZ28uG0Z0d3yI0EpqcpLR6BukoVRf3H4IbGCkPQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^3.0.0", + "npm-registry-fetch": "^4.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parse-asn1": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", @@ -1726,6 +3964,36 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "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 + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1771,6 +4039,12 @@ "pinkie": "^2.0.0" } }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -1786,6 +4060,47 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, + "prompts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", + "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -1795,6 +4110,12 @@ "ipaddr.js": "1.9.0" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, "psl": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", @@ -1822,6 +4143,29 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1880,6 +4224,64 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "rc-config-loader": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-2.0.5.tgz", + "integrity": "sha512-T464K2MQlnNWOblUDIglpFhyN+zYJq7jSlL++/N0hUkcmIXeNFumwXFVdtf8qhUGohn4RYQ0wdi74R575I44PQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "js-yaml": "^3.12.0", + "json5": "^2.1.0", + "object-assign": "^4.1.0", + "object-keys": "^1.0.12", + "path-exists": "^3.0.0", + "require-from-string": "^2.0.2" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "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 + } + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -1901,6 +4303,58 @@ } } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + }, + "registry-auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", + "integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==", + "dev": true, + "requires": { + "rc": "^1.2.8", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "req-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", + "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", + "dev": true, + "requires": { + "req-from": "^1.0.1" + } + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "dev": true, + "requires": { + "resolve-from": "^2.0.0" + } + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -1935,6 +4389,46 @@ } } }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "dev": true, + "requires": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, + "dependencies": { + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + } + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -1943,6 +4437,37 @@ "lowercase-keys": "^1.0.0" } }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -1962,6 +4487,15 @@ "safe-buffer": "^5.1.1" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", @@ -2006,10 +4540,33 @@ "commander": "~2.8.1" } }, - "semver": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", - "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==" + "semver": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", + "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver-utils": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz", + "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==", + "dev": true }, "send": { "version": "0.17.1", @@ -2095,6 +4652,54 @@ } } }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, "simple-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", @@ -2110,6 +4715,267 @@ "simple-concat": "^1.0.0" } }, + "sisteransi": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", + "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, + "sol-explore": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", + "integrity": "sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI=", + "dev": true + }, + "solidity-coverage": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.6.7.tgz", + "integrity": "sha512-Ga0Er5b25sFhy1uaYrQ+jQisP9819nj3zP1pfyAfE8Skg+/OBQ+Ev3sOmYQy9qZMjDuFJ7PCjuFVXdqdBO3cZw==", + "dev": true, + "requires": { + "death": "^1.1.0", + "ethereumjs-testrpc-sc": "6.5.1-sc.1", + "istanbul": "^0.4.5", + "keccakjs": "^0.2.1", + "req-cwd": "^1.0.1", + "shelljs": "^0.8.3", + "sol-explore": "^1.6.2", + "solidity-parser-antlr": "0.4.7", + "tree-kill": "^1.2.0", + "web3": "1.2.1", + "web3-eth-abi": "1.0.0-beta.55" + }, + "dependencies": { + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + }, + "dependencies": { + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "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" + } + } + } + }, + "ethers": { + "version": "4.0.39", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.39.tgz", + "integrity": "sha512-QVtC8TTUgTrnlQjQvdFJ7fkSWKwp8HVTbKRmrdbVryrPzJHMTf3WSeRNvLF2enGyAFtyHJyFNnjN0fSshcEr9w==", + "dev": true, + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", + "dev": true + }, + "scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", + "dev": true + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=", + "dev": true + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", + "dev": true + }, + "web3-eth-abi": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.55.tgz", + "integrity": "sha512-3h1xnm/vYmKUXTOYAOP0OsB5uijQV76pNNRGKOB6Dq6GR1pbcbD3WrB/4I643YA8l91t5FRzFzUiA3S77R2iqw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.3.1", + "ethers": "^4.0.27", + "lodash": "^4.17.11", + "web3-utils": "1.0.0-beta.55" + } + }, + "web3-utils": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.55.tgz", + "integrity": "sha512-ASWqUi8gtWK02Tp8ZtcoAbHenMpQXNvHrakgzvqTNNZn26wgpv+Q4mdPi0KOR6ZgHFL8R/9b5BBoUTglS1WPpg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.3.1", + "@types/bn.js": "^4.11.4", + "@types/node": "^10.12.18", + "bn.js": "4.11.8", + "eth-lib": "0.2.8", + "ethjs-unit": "^0.1.6", + "lodash": "^4.17.11", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "2.1.1" + } + } + } + }, + "solidity-parser-antlr": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.7.tgz", + "integrity": "sha512-iVjNhgqkXw+o+0E+xoLcji+3KuXLe8Rm8omUuVGhsV14+ZsTwQ70nhBRXg8O3t9xwdS0iST1q9NJ5IqHnqpWkA==", + "dev": true, + "requires": { + "npm-check-updates": "^3.1.11" + } + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "spawn-please": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-0.3.0.tgz", + "integrity": "sha1-2zOOxM/2Orxp8dDgjO6euL69nRE=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -2126,16 +4992,69 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "string.prototype.trim": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz", @@ -2179,6 +5098,15 @@ } } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -2187,6 +5115,12 @@ "is-natural-number": "^4.0.1" } }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -2195,6 +5129,21 @@ "is-hex-prefixed": "1.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + }, "swarm-js": { "version": "0.1.39", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", @@ -2288,11 +5237,30 @@ "xtend": "^4.0.0" } }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -2329,6 +5297,23 @@ } } }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "truffle": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-5.1.0.tgz", + "integrity": "sha512-RKij9cFhHeAb8HuP8D/llpcbe+k40fg8Q2SAeR+mkvlz9tid/opYkrWs9XN8eRQKCC0SSygrKBZLG3CMsNbXwQ==", + "dev": true, + "requires": { + "app-module-path": "^2.2.0", + "mocha": "5.2.0", + "original-require": "1.0.1" + } + }, "truffle-assertions": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/truffle-assertions/-/truffle-assertions-0.9.1.tgz", @@ -2362,10 +5347,20 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true }, "type-is": { "version": "1.6.18", @@ -2376,6 +5371,12 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -2384,6 +5385,33 @@ "is-typedarray": "^1.0.0" } }, + "uglify-js": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", + "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -2403,6 +5431,33 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -2413,6 +5468,26 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", + "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", + "dev": true, + "requires": { + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -2459,6 +5534,25 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2713,19 +5807,30 @@ "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", "requires": { "underscore": "1.9.1", - "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" + "web3-core-helpers": "1.2.1" }, "dependencies": { "websocket": { "version": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", - "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", + "from": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", "requires": { "debug": "^2.2.0", "es5-ext": "^0.10.50", "nan": "^2.14.0", "typedarray-to-buffer": "^3.1.5", "yaeti": "^0.0.6" + }, + "dependencies": { + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + } } } } @@ -2778,11 +5883,79 @@ "yaeti": "^0.0.6" } }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", @@ -2800,6 +5973,12 @@ } } }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, "xhr": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", @@ -2851,6 +6030,12 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", diff --git a/package.json b/package.json index f4d4ff4..18197e0 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "web3": "^1.2.1" }, "devDependencies": { - "@gnosis.pm/mock-contract": "^3.0.7" + "@gnosis.pm/mock-contract": "^3.0.7", + "solidity-coverage": "^0.6.7", + "truffle": "^5.0.44" } } From 35f73f4d69f1cd4c8f2fe9a1640d155b1764105d Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 21:58:05 +0100 Subject: [PATCH 02/10] adding library for exponential operations --- contracts/Treasurer.sol | 35 +++---- package-lock.json | 199 +++++++++++++++++++++++++++++++++++++--- package.json | 5 +- 3 files changed, 201 insertions(+), 38 deletions(-) diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 6a93313..575f453 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -3,10 +3,11 @@ pragma solidity ^0.5.2; import './yToken.sol'; import './oracle/Oracle.sol'; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - +import "./libraries/ExponentialOperations.sol"; contract Treasurer { using SafeMath for uint256; + using ExponentialOperations for uint256; struct Repo { uint256 locked; // Locked Collateral @@ -36,18 +37,6 @@ contract Treasurer { minCollateralRatio = minCollateralRatio_; } - // --- Math --- - uint constant WAD = 10 ** 18; - uint constant RAY = 10 ** 27; - - function wmul(uint x, uint y) internal pure returns (uint z) { - z = x.mul(y).add(WAD / 2) / WAD; - } - - function wdiv(uint x, uint y) internal pure returns (uint z) { - z = x.mul(WAD).add(y / 2) / y; - } - // --- Views --- // return unlocked collateral balance @@ -110,7 +99,7 @@ contract Treasurer { Repo memory repo = repos[series][msg.sender]; uint rate = peek(); // to add rate getter!!! - uint256 min = wmul(wmul(made, collateralRatio), rate); + uint256 min = made.wmul(collateralRatio).wmul(rate); require (paid >= min, "treasurer-make-insufficient-collateral-for-those-tokens"); // lock msg.sender Collateral, add debt @@ -142,7 +131,7 @@ contract Treasurer { uint rlocked = repo.locked.sub(released); uint rdebt = repo.debt.sub(credit); uint rate = peek(); // to add rate getter!!! - uint256 min = wmul(wmul(rdebt, collateralRatio), rate); + uint256 min = rdebt.wmul(collateralRatio).wmul(rate); uint deficiency = 0; if (min >= rlocked){ deficiency = min.sub(rlocked); @@ -166,7 +155,7 @@ contract Treasurer { uint rlocked = repo.locked.sub(released); uint rdebt = repo.debt.sub(credit); uint rate = peek(); // to add rate getter!!! - uint256 min = wmul(wmul(rdebt, collateralRatio), rate); + uint256 min = rdebt.wmul(collateralRatio).wmul(rate); require(rlocked >= min, "treasurer-wipe-insufficient-remaining-collateral"); //burn tokens @@ -192,7 +181,7 @@ contract Treasurer { //check that repo is in danger zone Repo memory repo = repos[series][bum]; uint rate = peek(); // to add rate getter!!! - uint256 min = wmul(wmul(repo.debt, minCollateralRatio), rate); + uint256 min = repo.debt.wmul(minCollateralRatio).wmul(rate); require(repo.locked < min, "treasurer-bite-still-safe"); //burn tokens @@ -200,15 +189,15 @@ contract Treasurer { yT.burnByOwner(msg.sender, amount); //update repo - uint256 bitten = wmul(wmul(amount, minCollateralRatio), rate); + uint256 bitten = amount.wmul(minCollateralRatio).wmul(rate); repo.locked = repo.locked.sub(bitten); repo.debt = repo.debt.sub(amount); repos[series][bum] = repo; - // send bitten funds msg.sender.transfer(bitten); } + // trigger settlement // series - yToken of debt to settle function settlement(uint series) external { @@ -231,12 +220,12 @@ contract Treasurer { yT.burnByOwner(msg.sender, amount); uint rate = settled[series]; - uint256 goods = wmul(amount, rate); + uint256 goods = amount.wmul(rate); msg.sender.transfer(goods); } - // close repo and retrieve remaining Ether // series - matured yToken + // close repo and retrieve remaining Ether function close(uint series) external { require(series < totalSeries, "treasurer-close-unissued-series"); require(now > yTokens[series].when, "treasurer-withdraw-yToken-hasnt-matured"); @@ -244,10 +233,10 @@ contract Treasurer { Repo memory repo = repos[series][msg.sender]; uint rate = settled[series]; // to add rate getter!!! - uint remainder = wmul(repo.debt, rate); + uint remainder = repo.debt.wmul(rate); require(repo.locked > remainder, "treasurer-settlement-repo-underfunded-at-settlement" ); - uint256 goods = repo.locked.sub(wmul(repo.debt, rate)); + uint256 goods = repo.locked.sub(repo.debt.wmul(rate)); repo.locked = 0; repo.debt = 0; repos[series][msg.sender] = repo; diff --git a/package-lock.json b/package-lock.json index e59c712..80616a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -840,6 +840,15 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1021,6 +1030,12 @@ "randombytes": "^2.0.0" } }, + "dir-to-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-to-object/-/dir-to-object-2.0.0.tgz", + "integrity": "sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==", + "dev": true + }, "dom-walk": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", @@ -1157,6 +1172,26 @@ "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -1172,6 +1207,15 @@ "es6-promise": "^4.0.3" } }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1202,6 +1246,23 @@ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, + "esprima-extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", + "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", + "dev": true, + "requires": { + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -2174,11 +2235,36 @@ } } }, + "ext": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.2.0.tgz", + "integrity": "sha512-0ccUQK/9e3NreLFg6K6np8aPyRgwycx+oFGtfx1dSp7Wj00Ozw9r05FgBRlzjf2XBM7LAzwgLyDscRrtSU91hA==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", + "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", + "dev": true, + "requires": { + "esprima-extract-comments": "^1.1.0", + "parse-code-context": "^1.0.0" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -3476,6 +3562,11 @@ "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "node-alias": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/node-alias/-/node-alias-1.0.4.tgz", @@ -3950,6 +4041,12 @@ "safe-buffer": "^5.1.1" } }, + "parse-code-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", + "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", + "dev": true + }, "parse-headers": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz", @@ -4050,6 +4147,86 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "prettier-plugin-solidity": { + "version": "1.0.0-alpha.34", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.34.tgz", + "integrity": "sha512-cg/HrnS4P6m7rdnazZt3QdN7TwuW+TO5quLpTLzvN2BTsbyNFjBjTBUFIJwlFVhjUjw8mQ2uxKfk3b7pSvXJyw==", + "dev": true, + "requires": { + "dir-to-object": "^2.0.0", + "emoji-regex": "^8.0.0", + "escape-string-regexp": "^2.0.0", + "extract-comments": "^1.1.0", + "prettier": "^1.15.3", + "semver": "^6.3.0", + "solidity-parser-antlr": "^0.4.11", + "string-width": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solidity-parser-antlr": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.11.tgz", + "integrity": "sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "process": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", @@ -5347,6 +5524,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -5807,30 +5989,19 @@ "integrity": "sha512-oqsQXzu+ejJACVHy864WwIyw+oB21nw/pI65/sD95Zi98+/HQzFfNcIFneF1NC4bVF3VNX4YHTNq2I2o97LAiA==", "requires": { "underscore": "1.9.1", - "web3-core-helpers": "1.2.1" + "web3-core-helpers": "1.2.1", + "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" }, "dependencies": { "websocket": { "version": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", - "from": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", + "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" - }, - "dependencies": { - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - } } } } diff --git a/package.json b/package.json index 18197e0..dcdd7a2 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "test": "test" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "prettier:solidity": "./node_modules/.bin/prettier --write 'contracts/**/*.sol'" }, "keywords": [], "author": "", @@ -22,6 +23,8 @@ }, "devDependencies": { "@gnosis.pm/mock-contract": "^3.0.7", + "prettier": "^1.19.1", + "prettier-plugin-solidity": "^1.0.0-alpha.34", "solidity-coverage": "^0.6.7", "truffle": "^5.0.44" } From 1eb96e61f43a71ce81eb5b46b47e89058d04d0fe Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 21:59:02 +0100 Subject: [PATCH 03/10] linting all the solidity code --- contracts/Migrations.sol | 30 +- contracts/Treasurer.sol | 541 ++++++++++-------- contracts/imports/Imports.sol | 5 +- .../interfaces/UniswapExchangeInterface.sol | 158 ++++- .../interfaces/UniswapFactoryInterface.sol | 10 +- contracts/oracle/Oracle.sol | 22 +- .../test-contracts/uniswapexchangemock.sol | 9 +- .../test-contracts/uniswapfactorymock.sol | 21 +- contracts/yToken.sol | 19 +- package.json | 2 +- 10 files changed, 499 insertions(+), 318 deletions(-) diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index c378ffb..74ecda2 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,23 +1,23 @@ pragma solidity >=0.4.21 <0.6.0; contract Migrations { - address public owner; - uint public last_completed_migration; + address public owner; + uint256 public last_completed_migration; - constructor() public { - owner = msg.sender; - } + constructor() public { + owner = msg.sender; + } - modifier restricted() { - if (msg.sender == owner) _; - } + modifier restricted() { + if (msg.sender == owner) _; + } - function setCompleted(uint completed) public restricted { - last_completed_migration = completed; - } + function setCompleted(uint256 completed) public restricted { + last_completed_migration = completed; + } - function upgrade(address new_address) public restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } + function upgrade(address new_address) public restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } } diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 575f453..6e76634 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -1,246 +1,309 @@ pragma solidity ^0.5.2; -import './yToken.sol'; -import './oracle/Oracle.sol'; +import "./yToken.sol"; +import "./oracle/Oracle.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./libraries/ExponentialOperations.sol"; contract Treasurer { - using SafeMath for uint256; - using ExponentialOperations for uint256; - - struct Repo { - uint256 locked; // Locked Collateral - uint256 unminted; // unminted - uint256 debt; // Debt - } - - struct yieldT { - address where; // contract address of yToken - uint256 when; // maturity time of yToken - } - - mapping (uint => yieldT) public yTokens; - mapping (uint => mapping (address => Repo)) public repos; // locked ETH and debt - mapping (address => uint) public unlocked; // unlocked ETH - mapping (uint => uint) public settled; // settlement price of collateral - uint[] public issuedSeries; - address public owner; - address public oracle; - uint public collateralRatio; // collateralization ratio - uint public minCollateralRatio; // minimum collateralization ratio - uint public totalSeries = 0; - - constructor(address owner_, uint collateralRatio_, uint minCollateralRatio_) public { - owner = owner_; - collateralRatio = collateralRatio_; - minCollateralRatio = minCollateralRatio_; - } - - // --- Views --- - - // return unlocked collateral balance - function balance(address usr) public view returns (uint){ - return unlocked[usr]; - } - - // --- Actions --- - - // provide address to oracle - // oracle_ - address of the oracle contract - function setOracle(address oracle_) external { - require(msg.sender == owner); - oracle = oracle_; - } - - // get oracle value - function peek() public view returns (uint r){ - Oracle _oracle = Oracle(oracle); - r = _oracle.read(); - } - - // issue new yToken - function issue(uint256 when) external returns (uint series) { - require(msg.sender == owner, "treasurer-issue-only-owner-may-issue"); - require(when > now, "treasurer-issue-maturity-is-in-past"); - series = totalSeries; - require(yTokens[series].when == 0, "treasurer-issue-may-not-reissue-series"); - yToken _token = new yToken(when); - address _a = address(_token); - yieldT memory yT = yieldT(_a, when); - yTokens[series] = yT; - issuedSeries.push(series); - totalSeries = totalSeries + 1; - } - - // add collateral to repo - function join() external payable { - require(msg.value >= 0, "treasurer-join-collateralRatio-include-deposit"); - unlocked[msg.sender] = unlocked[msg.sender].add(msg.value); - } - - // remove collateral from repo - // amount - amount of ETH to remove from unlocked account - // TO-DO: Update as described in https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ - function exit(uint amount) external { - require(amount >= 0, "treasurer-exit-insufficient-balance"); - unlocked[msg.sender] = unlocked[msg.sender].sub(amount); - msg.sender.transfer(amount); - } - - // make a new yToken - // series - yToken to mint - // made - amount of yToken to mint - // paid - amount of collateral to lock up - function make(uint series, uint made, uint paid) external { - require(series < totalSeries, "treasurer-make-unissued-series"); - // first check if sufficient capital to lock up - require(unlocked[msg.sender] >= paid, "treasurer-make-insufficient-unlocked-to-lock"); - - Repo memory repo = repos[series][msg.sender]; - uint rate = peek(); // to add rate getter!!! - uint256 min = made.wmul(collateralRatio).wmul(rate); - require (paid >= min, "treasurer-make-insufficient-collateral-for-those-tokens"); - - // lock msg.sender Collateral, add debt - unlocked[msg.sender] = unlocked[msg.sender].sub(paid); - repo.locked = repo.locked.add(paid); - repo.debt = repo.debt.add(made); - repos[series][msg.sender] = repo; - - // mint new yTokens - // first, ensure yToken is initialized and matures in the future - require(yTokens[series].when > now, "treasurer-make-invalid-or-matured-ytoken"); - yToken yT = yToken(yTokens[series].where); - address sender = msg.sender; - yT.mint(sender, made); - } - - // check that wipe leaves sufficient collateral - // series - yToken to mint - // credit - amount of yToken to wipe - // released - amount of collateral to free - // returns (true, 0) if sufficient collateral would remain - // returns (false, deficiency) if sufficient collateral would not remain - function wipeCheck(uint series, uint credit, uint released) public view returns (bool, uint) { - require(series < totalSeries, "treasurer-wipeCheck-unissued-series"); - Repo memory repo = repos[series][msg.sender]; - require(repo.locked >= released, "treasurer-wipe-release-more-than-locked"); - require(repo.debt >= credit, "treasurer-wipe-wipe-more-debt-than-present"); - // if would be undercollateralized after freeing clean, fail - uint rlocked = repo.locked.sub(released); - uint rdebt = repo.debt.sub(credit); - uint rate = peek(); // to add rate getter!!! - uint256 min = rdebt.wmul(collateralRatio).wmul(rate); - uint deficiency = 0; - if (min >= rlocked){ - deficiency = min.sub(rlocked); - } - return (rlocked >= min, deficiency); - } - - // wipe repo debt with yToken - // series - yToken to mint - // credit - amount of yToken to wipe - // released - amount of collateral to free - function wipe(uint series, uint credit, uint released) external { - require(series < totalSeries, "treasurer-wipe-unissued-series"); - // if yToken has matured, should call resolve - require(now < yTokens[series].when, "treasurer-wipe-yToken-has-matured"); - - Repo memory repo = repos[series][msg.sender]; - require(repo.locked >= released, "treasurer-wipe-release-more-than-locked"); - require(repo.debt >= credit, "treasurer-wipe-wipe-more-debt-than-present"); - // if would be undercollateralized after freeing clean, fail - uint rlocked = repo.locked.sub(released); - uint rdebt = repo.debt.sub(credit); - uint rate = peek(); // to add rate getter!!! - uint256 min = rdebt.wmul(collateralRatio).wmul(rate); - require(rlocked >= min, "treasurer-wipe-insufficient-remaining-collateral"); - - //burn tokens - yToken yT = yToken(yTokens[series].where); - require(yT.balanceOf(msg.sender) > credit, "treasurer-wipe-insufficient-token-balance"); - yT.burnFrom(msg.sender, credit); - - // reduce the collateral and the debt - repo.locked = repo.locked.sub(released); - repo.debt = repo.debt.sub(credit); - repos[series][msg.sender] = repo; - - // add collateral back to the unlocked - unlocked[msg.sender] = unlocked[msg.sender].add(released); - } - - // liquidate a repo - // series - yToken of debt to buy - // bum - owner of the undercollateralized repo - // amount - amount of yToken debt to buy - function liquidate(uint series, address bum, uint256 amount) external { - require(series < totalSeries, "treasurer-liquidate-unissued-series"); - //check that repo is in danger zone - Repo memory repo = repos[series][bum]; - uint rate = peek(); // to add rate getter!!! - uint256 min = repo.debt.wmul(minCollateralRatio).wmul(rate); - require(repo.locked < min, "treasurer-bite-still-safe"); - - //burn tokens - yToken yT = yToken(yTokens[series].where); - yT.burnByOwner(msg.sender, amount); - - //update repo - uint256 bitten = amount.wmul(minCollateralRatio).wmul(rate); - repo.locked = repo.locked.sub(bitten); - repo.debt = repo.debt.sub(amount); - repos[series][bum] = repo; - // send bitten funds - msg.sender.transfer(bitten); - } - - - // trigger settlement - // series - yToken of debt to settle - function settlement(uint series) external { - require(series < totalSeries, "treasurer-settlement-unissued-series"); - require(now > yTokens[series].when, "treasurer-settlement-yToken-hasnt-matured"); - require(settled[series] == 0, "treasurer-settlement-settlement-already-called"); - settled[series] = peek(); - } - - - // redeem tokens for underlying Ether - // series - matured yToken - // amount - amount of yToken to close - function withdraw(uint series, uint256 amount) external { - require(series < totalSeries, "treasurer-withdraw-unissued-series"); - require(now > yTokens[series].when, "treasurer-withdraw-yToken-hasnt-matured"); - require(settled[series] != 0, "treasurer-settlement-settlement-not-yet-called"); - - yToken yT = yToken(yTokens[series].where); - yT.burnByOwner(msg.sender, amount); - - uint rate = settled[series]; - uint256 goods = amount.wmul(rate); - msg.sender.transfer(goods); - } - - // series - matured yToken - // close repo and retrieve remaining Ether - function close(uint series) external { - require(series < totalSeries, "treasurer-close-unissued-series"); - require(now > yTokens[series].when, "treasurer-withdraw-yToken-hasnt-matured"); - require(settled[series] != 0, "treasurer-settlement-settlement-not-yet-called"); - - Repo memory repo = repos[series][msg.sender]; - uint rate = settled[series]; // to add rate getter!!! - uint remainder = repo.debt.wmul(rate); - - require(repo.locked > remainder, "treasurer-settlement-repo-underfunded-at-settlement" ); - uint256 goods = repo.locked.sub(repo.debt.wmul(rate)); - repo.locked = 0; - repo.debt = 0; - repos[series][msg.sender] = repo; - - msg.sender.transfer(goods); - } + using SafeMath for uint256; + using ExponentialOperations for uint256; + + struct Repo { + uint256 locked; // Locked Collateral + uint256 unminted; // unminted + uint256 debt; // Debt + } + + struct yieldT { + address where; // contract address of yToken + uint256 when; // maturity time of yToken + } + + mapping(uint256 => yieldT) public yTokens; + mapping(uint256 => mapping(address => Repo)) public repos; // locked ETH and debt + mapping(address => uint256) public unlocked; // unlocked ETH + mapping(uint256 => uint256) public settled; // settlement price of collateral + uint256[] public issuedSeries; + address public owner; + address public oracle; + uint256 public collateralRatio; // collateralization ratio + uint256 public minCollateralRatio; // minimum collateralization ratio + uint256 public totalSeries = 0; + + constructor( + address owner_, + uint256 collateralRatio_, + uint256 minCollateralRatio_ + ) public { + owner = owner_; + collateralRatio = collateralRatio_; + minCollateralRatio = minCollateralRatio_; + } + + // --- Views --- + + // return unlocked collateral balance + function balance(address usr) public view returns (uint256) { + return unlocked[usr]; + } + + // --- Actions --- + + // provide address to oracle + // oracle_ - address of the oracle contract + function setOracle(address oracle_) external { + require(msg.sender == owner); + oracle = oracle_; + } + + // get oracle value + function peek() public view returns (uint256 r) { + Oracle _oracle = Oracle(oracle); + r = _oracle.read(); + } + + // issue new yToken + function issue(uint256 when) external returns (uint256 series) { + require(msg.sender == owner, "treasurer-issue-only-owner-may-issue"); + require(when > now, "treasurer-issue-maturity-is-in-past"); + series = totalSeries; + require( + yTokens[series].when == 0, + "treasurer-issue-may-not-reissue-series" + ); + yToken _token = new yToken(when); + address _a = address(_token); + yieldT memory yT = yieldT(_a, when); + yTokens[series] = yT; + issuedSeries.push(series); + totalSeries = totalSeries + 1; + } + + // add collateral to repo + function join() external payable { + require( + msg.value >= 0, + "treasurer-join-collateralRatio-include-deposit" + ); + unlocked[msg.sender] = unlocked[msg.sender].add(msg.value); + } + + // remove collateral from repo + // amount - amount of ETH to remove from unlocked account + // TO-DO: Update as described in https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ + function exit(uint256 amount) external { + require(amount >= 0, "treasurer-exit-insufficient-balance"); + unlocked[msg.sender] = unlocked[msg.sender].sub(amount); + msg.sender.transfer(amount); + } + + // make a new yToken + // series - yToken to mint + // made - amount of yToken to mint + // paid - amount of collateral to lock up + function make(uint256 series, uint256 made, uint256 paid) external { + require(series < totalSeries, "treasurer-make-unissued-series"); + // first check if sufficient capital to lock up + require( + unlocked[msg.sender] >= paid, + "treasurer-make-insufficient-unlocked-to-lock" + ); + + Repo memory repo = repos[series][msg.sender]; + uint256 rate = peek(); // to add rate getter!!! + uint256 min = made.wmul(collateralRatio).wmul(rate); + require( + paid >= min, + "treasurer-make-insufficient-collateral-for-those-tokens" + ); + + // lock msg.sender Collateral, add debt + unlocked[msg.sender] = unlocked[msg.sender].sub(paid); + repo.locked = repo.locked.add(paid); + repo.debt = repo.debt.add(made); + repos[series][msg.sender] = repo; + + // mint new yTokens + // first, ensure yToken is initialized and matures in the future + require( + yTokens[series].when > now, + "treasurer-make-invalid-or-matured-ytoken" + ); + yToken yT = yToken(yTokens[series].where); + address sender = msg.sender; + yT.mint(sender, made); + } + + // check that wipe leaves sufficient collateral + // series - yToken to mint + // credit - amount of yToken to wipe + // released - amount of collateral to free + // returns (true, 0) if sufficient collateral would remain + // returns (false, deficiency) if sufficient collateral would not remain + function wipeCheck(uint256 series, uint256 credit, uint256 released) + public + view + returns (bool, uint256) + { + require(series < totalSeries, "treasurer-wipeCheck-unissued-series"); + Repo memory repo = repos[series][msg.sender]; + require( + repo.locked >= released, + "treasurer-wipe-release-more-than-locked" + ); + require( + repo.debt >= credit, + "treasurer-wipe-wipe-more-debt-than-present" + ); + // if would be undercollateralized after freeing clean, fail + uint256 rlocked = repo.locked.sub(released); + uint256 rdebt = repo.debt.sub(credit); + uint256 rate = peek(); // to add rate getter!!! + uint256 min = rdebt.wmul(collateralRatio).wmul(rate); + uint256 deficiency = 0; + if (min >= rlocked) { + deficiency = min.sub(rlocked); + } + return (rlocked >= min, deficiency); + } + + // wipe repo debt with yToken + // series - yToken to mint + // credit - amount of yToken to wipe + // released - amount of collateral to free + function wipe(uint256 series, uint256 credit, uint256 released) external { + require(series < totalSeries, "treasurer-wipe-unissued-series"); + // if yToken has matured, should call resolve + require( + now < yTokens[series].when, + "treasurer-wipe-yToken-has-matured" + ); + + Repo memory repo = repos[series][msg.sender]; + require( + repo.locked >= released, + "treasurer-wipe-release-more-than-locked" + ); + require( + repo.debt >= credit, + "treasurer-wipe-wipe-more-debt-than-present" + ); + // if would be undercollateralized after freeing clean, fail + uint256 rlocked = repo.locked.sub(released); + uint256 rdebt = repo.debt.sub(credit); + uint256 rate = peek(); // to add rate getter!!! + uint256 min = rdebt.wmul(collateralRatio).wmul(rate); + require( + rlocked >= min, + "treasurer-wipe-insufficient-remaining-collateral" + ); + + //burn tokens + yToken yT = yToken(yTokens[series].where); + require( + yT.balanceOf(msg.sender) > credit, + "treasurer-wipe-insufficient-token-balance" + ); + yT.burnFrom(msg.sender, credit); + + // reduce the collateral and the debt + repo.locked = repo.locked.sub(released); + repo.debt = repo.debt.sub(credit); + repos[series][msg.sender] = repo; + + // add collateral back to the unlocked + unlocked[msg.sender] = unlocked[msg.sender].add(released); + } + + // liquidate a repo + // series - yToken of debt to buy + // bum - owner of the undercollateralized repo + // amount - amount of yToken debt to buy + function liquidate(uint256 series, address bum, uint256 amount) external { + require(series < totalSeries, "treasurer-liquidate-unissued-series"); + //check that repo is in danger zone + Repo memory repo = repos[series][bum]; + uint256 rate = peek(); // to add rate getter!!! + uint256 min = repo.debt.wmul(minCollateralRatio).wmul(rate); + require(repo.locked < min, "treasurer-bite-still-safe"); + + //burn tokens + yToken yT = yToken(yTokens[series].where); + yT.burnByOwner(msg.sender, amount); + + //update repo + uint256 bitten = amount.wmul(minCollateralRatio).wmul(rate); + repo.locked = repo.locked.sub(bitten); + repo.debt = repo.debt.sub(amount); + repos[series][bum] = repo; + // send bitten funds + msg.sender.transfer(bitten); + } + + // trigger settlement + // series - yToken of debt to settle + function settlement(uint256 series) external { + require(series < totalSeries, "treasurer-settlement-unissued-series"); + require( + now > yTokens[series].when, + "treasurer-settlement-yToken-hasnt-matured" + ); + require( + settled[series] == 0, + "treasurer-settlement-settlement-already-called" + ); + settled[series] = peek(); + } + + // redeem tokens for underlying Ether + // series - matured yToken + // amount - amount of yToken to close + function withdraw(uint256 series, uint256 amount) external { + require(series < totalSeries, "treasurer-withdraw-unissued-series"); + require( + now > yTokens[series].when, + "treasurer-withdraw-yToken-hasnt-matured" + ); + require( + settled[series] != 0, + "treasurer-settlement-settlement-not-yet-called" + ); + + yToken yT = yToken(yTokens[series].where); + yT.burnByOwner(msg.sender, amount); + + uint256 rate = settled[series]; + uint256 goods = amount.wmul(rate); + msg.sender.transfer(goods); + } + + // series - matured yToken + // close repo and retrieve remaining Ether + function close(uint256 series) external { + require(series < totalSeries, "treasurer-close-unissued-series"); + require( + now > yTokens[series].when, + "treasurer-withdraw-yToken-hasnt-matured" + ); + require( + settled[series] != 0, + "treasurer-settlement-settlement-not-yet-called" + ); + + Repo memory repo = repos[series][msg.sender]; + uint256 rate = settled[series]; // to add rate getter!!! + uint256 remainder = repo.debt.wmul(rate); + + require( + repo.locked > remainder, + "treasurer-settlement-repo-underfunded-at-settlement" + ); + uint256 goods = repo.locked.sub(repo.debt.wmul(rate)); + repo.locked = 0; + repo.debt = 0; + repos[series][msg.sender] = repo; + + msg.sender.transfer(goods); + } } diff --git a/contracts/imports/Imports.sol b/contracts/imports/Imports.sol index 371eda2..b69b50e 100644 --- a/contracts/imports/Imports.sol +++ b/contracts/imports/Imports.sol @@ -4,7 +4,4 @@ pragma solidity ^0.5.2; // available when working from truffle console. import "@gnosis.pm/mock-contract/contracts/MockContract.sol"; - -contract DoesNothing { - -} +contract DoesNothing {} diff --git a/contracts/interfaces/UniswapExchangeInterface.sol b/contracts/interfaces/UniswapExchangeInterface.sol index 588a3c7..0ac2197 100644 --- a/contracts/interfaces/UniswapExchangeInterface.sol +++ b/contracts/interfaces/UniswapExchangeInterface.sol @@ -7,41 +7,151 @@ contract UniswapExchangeInterface { // Address of Uniswap Factory function factoryAddress() external view returns (address factory); // Provide Liquidity - function addLiquidity(uint256 min_liquidity, uint256 max_tokens, uint256 deadline) external payable returns (uint256); - function removeLiquidity(uint256 amount, uint256 min_eth, uint256 min_tokens, uint256 deadline) external returns (uint256, uint256); + function addLiquidity( + uint256 min_liquidity, + uint256 max_tokens, + uint256 deadline + ) external payable returns (uint256); + function removeLiquidity( + uint256 amount, + uint256 min_eth, + uint256 min_tokens, + uint256 deadline + ) external returns (uint256, uint256); // Get Prices - function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought); - function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold); - function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought); - function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold); + function getEthToTokenInputPrice(uint256 eth_sold) + external + view + returns (uint256 tokens_bought); + function getEthToTokenOutputPrice(uint256 tokens_bought) + external + view + returns (uint256 eth_sold); + function getTokenToEthInputPrice(uint256 tokens_sold) + external + view + returns (uint256 eth_bought); + function getTokenToEthOutputPrice(uint256 eth_bought) + external + view + returns (uint256 tokens_sold); // Trade ETH to ERC20 - function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) external payable returns (uint256 tokens_bought); - function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256 tokens_bought); - function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline) external payable returns (uint256 eth_sold); - function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256 eth_sold); + function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) + external + payable + returns (uint256 tokens_bought); + function ethToTokenTransferInput( + uint256 min_tokens, + uint256 deadline, + address recipient + ) external payable returns (uint256 tokens_bought); + function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline) + external + payable + returns (uint256 eth_sold); + function ethToTokenTransferOutput( + uint256 tokens_bought, + uint256 deadline, + address recipient + ) external payable returns (uint256 eth_sold); // Trade ERC20 to ETH - function tokenToEthSwapInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline) external returns (uint256 eth_bought); - function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient) external returns (uint256 eth_bought); - function tokenToEthSwapOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline) external returns (uint256 tokens_sold); - function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256 tokens_sold); + function tokenToEthSwapInput( + uint256 tokens_sold, + uint256 min_eth, + uint256 deadline + ) external returns (uint256 eth_bought); + function tokenToEthTransferInput( + uint256 tokens_sold, + uint256 min_eth, + uint256 deadline, + address recipient + ) external returns (uint256 eth_bought); + function tokenToEthSwapOutput( + uint256 eth_bought, + uint256 max_tokens, + uint256 deadline + ) external returns (uint256 tokens_sold); + function tokenToEthTransferOutput( + uint256 eth_bought, + uint256 max_tokens, + uint256 deadline, + address recipient + ) external returns (uint256 tokens_sold); // Trade ERC20 to ERC20 - function tokenToTokenSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address token_addr) external returns (uint256 tokens_bought); - function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_bought); - function tokenToTokenSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address token_addr) external returns (uint256 tokens_sold); - function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_sold); + function tokenToTokenSwapInput( + uint256 tokens_sold, + uint256 min_tokens_bought, + uint256 min_eth_bought, + uint256 deadline, + address token_addr + ) external returns (uint256 tokens_bought); + function tokenToTokenTransferInput( + uint256 tokens_sold, + uint256 min_tokens_bought, + uint256 min_eth_bought, + uint256 deadline, + address recipient, + address token_addr + ) external returns (uint256 tokens_bought); + function tokenToTokenSwapOutput( + uint256 tokens_bought, + uint256 max_tokens_sold, + uint256 max_eth_sold, + uint256 deadline, + address token_addr + ) external returns (uint256 tokens_sold); + function tokenToTokenTransferOutput( + uint256 tokens_bought, + uint256 max_tokens_sold, + uint256 max_eth_sold, + uint256 deadline, + address recipient, + address token_addr + ) external returns (uint256 tokens_sold); // Trade ERC20 to Custom Pool - function tokenToExchangeSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address exchange_addr) external returns (uint256 tokens_bought); - function tokenToExchangeTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_bought); - function tokenToExchangeSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address exchange_addr) external returns (uint256 tokens_sold); - function tokenToExchangeTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_sold); + function tokenToExchangeSwapInput( + uint256 tokens_sold, + uint256 min_tokens_bought, + uint256 min_eth_bought, + uint256 deadline, + address exchange_addr + ) external returns (uint256 tokens_bought); + function tokenToExchangeTransferInput( + uint256 tokens_sold, + uint256 min_tokens_bought, + uint256 min_eth_bought, + uint256 deadline, + address recipient, + address exchange_addr + ) external returns (uint256 tokens_bought); + function tokenToExchangeSwapOutput( + uint256 tokens_bought, + uint256 max_tokens_sold, + uint256 max_eth_sold, + uint256 deadline, + address exchange_addr + ) external returns (uint256 tokens_sold); + function tokenToExchangeTransferOutput( + uint256 tokens_bought, + uint256 max_tokens_sold, + uint256 max_eth_sold, + uint256 deadline, + address recipient, + address exchange_addr + ) external returns (uint256 tokens_sold); // ERC20 comaptibility for liquidity tokens bytes32 public name; bytes32 public symbol; uint256 public decimals; function transfer(address _to, uint256 _value) external returns (bool); - function transferFrom(address _from, address _to, uint256 value) external returns (bool); + function transferFrom(address _from, address _to, uint256 value) + external + returns (bool); function approve(address _spender, uint256 _value) external returns (bool); - function allowance(address _owner, address _spender) external view returns (uint256); + function allowance(address _owner, address _spender) + external + view + returns (uint256); function balanceOf(address _owner) external view returns (uint256); function totalSupply() external view returns (uint256); // Never use diff --git a/contracts/interfaces/UniswapFactoryInterface.sol b/contracts/interfaces/UniswapFactoryInterface.sol index 1c4e3be..b5ea94e 100644 --- a/contracts/interfaces/UniswapFactoryInterface.sol +++ b/contracts/interfaces/UniswapFactoryInterface.sol @@ -8,9 +8,15 @@ contract UniswapFactoryInterface { // Create Exchange function createExchange(address token) external returns (address exchange); // Get Exchange and Token Info - function getExchange(address token) external view returns (address exchange); + function getExchange(address token) + external + view + returns (address exchange); function getToken(address exchange) external view returns (address token); - function getTokenWithId(uint256 tokenId) external view returns (address token); + function getTokenWithId(uint256 tokenId) + external + view + returns (address token); // Never use function initializeFactory(address template) external; } diff --git a/contracts/oracle/Oracle.sol b/contracts/oracle/Oracle.sol index af05ede..e617c22 100644 --- a/contracts/oracle/Oracle.sol +++ b/contracts/oracle/Oracle.sol @@ -2,19 +2,19 @@ pragma solidity ^0.5.2; //Using fake contract instead of abstract for mocking contract Oracle { - uint256 val; + uint256 val; - function set(uint256 _value) public { - val = _value; - } + function set(uint256 _value) public { + val = _value; + } - function read() external view returns (uint256) { - require(val > 0, "Invalid price feed"); - return val; - } + function read() external view returns (uint256) { + require(val > 0, "Invalid price feed"); + return val; + } - function peek() external view returns (uint256,bool) { - return (val, val > 0); - } + function peek() external view returns (uint256, bool) { + return (val, val > 0); + } } diff --git a/contracts/test-contracts/uniswapexchangemock.sol b/contracts/test-contracts/uniswapexchangemock.sol index 43a6300..6786aee 100644 --- a/contracts/test-contracts/uniswapexchangemock.sol +++ b/contracts/test-contracts/uniswapexchangemock.sol @@ -2,9 +2,12 @@ pragma solidity ^0.5.2; // Solidity Interface contract UniswapExchangeMock { - - function getEthToTokenInputPrice(uint256 eth_sold) external pure returns (uint256 tokens_bought){ - return 0.98 ether + (eth_sold - eth_sold); + function getEthToTokenInputPrice(uint256 eth_sold) + external + pure + returns (uint256 tokens_bought) + { + return 0.98 ether + (eth_sold - eth_sold); } } diff --git a/contracts/test-contracts/uniswapfactorymock.sol b/contracts/test-contracts/uniswapfactorymock.sol index 341ab71..d191540 100644 --- a/contracts/test-contracts/uniswapfactorymock.sol +++ b/contracts/test-contracts/uniswapfactorymock.sol @@ -1,20 +1,23 @@ pragma solidity ^0.5.2; // Solidity Interface -import './uniswapexchangemock.sol'; +import "./uniswapexchangemock.sol"; contract UniswapFactoryMock { - mapping (address => address) exchanges; + mapping(address => address) exchanges; // Create Exchange - function createExchange(address token) external returns (address exchange) - { - UniswapExchangeMock _mock = new UniswapExchangeMock(); - exchanges[token] = address(_mock); - return address(_mock); + function createExchange(address token) external returns (address exchange) { + UniswapExchangeMock _mock = new UniswapExchangeMock(); + exchanges[token] = address(_mock); + return address(_mock); } // Get Exchange and Token Info - function getExchange(address token) external view returns (address exchange){ - return exchanges[token]; + function getExchange(address token) + external + view + returns (address exchange) + { + return exchanges[token]; } // Never use } diff --git a/contracts/yToken.sol b/contracts/yToken.sol index a6122cb..8b3d073 100644 --- a/contracts/yToken.sol +++ b/contracts/yToken.sol @@ -1,18 +1,17 @@ pragma solidity ^0.5.2; -import 'openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol'; -import 'openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol'; - +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol"; contract yToken is ERC20Burnable, ERC20Mintable { - uint256 public when; + uint256 public when; - constructor(uint256 when_) public { - when = when_; - } + constructor(uint256 when_) public { + when = when_; + } - function burnByOwner(address account, uint256 amount) external onlyMinter { - _burn(account, amount); - } + function burnByOwner(address account, uint256 amount) external onlyMinter { + _burn(account, amount); + } } diff --git a/package.json b/package.json index dcdd7a2..2e6db5e 100644 --- a/package.json +++ b/package.json @@ -28,4 +28,4 @@ "solidity-coverage": "^0.6.7", "truffle": "^5.0.44" } -} +} \ No newline at end of file From a2a46e060aa94675bfa51eb84549d8c96f64f243 Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 22:06:06 +0100 Subject: [PATCH 04/10] adding prettier linting configuration, and missing Library for ExponentialOperations.sol --- .prettierrc | 15 +++++++++++++++ contracts/libraries/ExponentialOperations.sol | 18 ++++++++++++++++++ package.json | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 .prettierrc create mode 100644 contracts/libraries/ExponentialOperations.sol diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e368cfe --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false, + "explicitTypes": "always" + } + } + ] +} diff --git a/contracts/libraries/ExponentialOperations.sol b/contracts/libraries/ExponentialOperations.sol new file mode 100644 index 0000000..db3fd92 --- /dev/null +++ b/contracts/libraries/ExponentialOperations.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.2; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +library ExponentialOperations { + using SafeMath for uint256; + + uint256 constant WAD = 10**18; + uint256 constant RAY = 10**27; + + function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = x.mul(y).add(WAD / 2) / WAD; + } + + function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = x.mul(WAD).add(y / 2) / y; + } +} diff --git a/package.json b/package.json index 2e6db5e..dcdd7a2 100644 --- a/package.json +++ b/package.json @@ -28,4 +28,4 @@ "solidity-coverage": "^0.6.7", "truffle": "^5.0.44" } -} \ No newline at end of file +} From 5a3f2ac06e4b43bb1ed1a50b863040b134a4dade Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 22:16:10 +0100 Subject: [PATCH 05/10] owner management via library --- contracts/Treasurer.sol | 20 ++++++++------------ migrations/2_deploy.js | 11 ++--------- migrations/4_deploy_uniswap_mocks.js | 12 ++++++------ 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 6e76634..b9879cc 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -4,8 +4,9 @@ import "./yToken.sol"; import "./oracle/Oracle.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./libraries/ExponentialOperations.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -contract Treasurer { +contract Treasurer is Ownable { using SafeMath for uint256; using ExponentialOperations for uint256; @@ -25,18 +26,15 @@ contract Treasurer { mapping(address => uint256) public unlocked; // unlocked ETH mapping(uint256 => uint256) public settled; // settlement price of collateral uint256[] public issuedSeries; - address public owner; address public oracle; uint256 public collateralRatio; // collateralization ratio uint256 public minCollateralRatio; // minimum collateralization ratio uint256 public totalSeries = 0; - constructor( - address owner_, - uint256 collateralRatio_, - uint256 minCollateralRatio_ - ) public { - owner = owner_; + constructor(uint256 collateralRatio_, uint256 minCollateralRatio_) + public + Ownable() + { collateralRatio = collateralRatio_; minCollateralRatio = minCollateralRatio_; } @@ -52,8 +50,7 @@ contract Treasurer { // provide address to oracle // oracle_ - address of the oracle contract - function setOracle(address oracle_) external { - require(msg.sender == owner); + function setOracle(address oracle_) external onlyOwner { oracle = oracle_; } @@ -64,8 +61,7 @@ contract Treasurer { } // issue new yToken - function issue(uint256 when) external returns (uint256 series) { - require(msg.sender == owner, "treasurer-issue-only-owner-may-issue"); + function issue(uint256 when) external onlyOwner returns (uint256 series) { require(when > now, "treasurer-issue-maturity-is-in-past"); series = totalSeries; require( diff --git a/migrations/2_deploy.js b/migrations/2_deploy.js index 6df6e07..f2f0e03 100644 --- a/migrations/2_deploy.js +++ b/migrations/2_deploy.js @@ -1,17 +1,10 @@ const Treasurer = artifacts.require("Treasurer"); -const Token = artifacts.require("yToken"); +const Token = artifacts.require("yToken"); const MockContract = artifacts.require("./MockContract"); module.exports = function(deployer, network, accounts) { - //if (network == "") //Token stands in for Dai deployer.deploy(MockContract); - deployer.deploy( - Treasurer, - accounts[0], - web3.utils.toWei("1.5"), - web3.utils.toWei("1.05") - ); - + deployer.deploy(Treasurer, web3.utils.toWei("1.5"), web3.utils.toWei("1.05")); }; diff --git a/migrations/4_deploy_uniswap_mocks.js b/migrations/4_deploy_uniswap_mocks.js index 077a8d4..8d8a13f 100644 --- a/migrations/4_deploy_uniswap_mocks.js +++ b/migrations/4_deploy_uniswap_mocks.js @@ -9,16 +9,16 @@ setup = async () => { var rate = web3.utils.toWei(".01"); await oracle.set(rate); await treasurer.setOracle(oracle.address); - var thedate = Math.floor(Date.now() / 1000) + (24*60*60)*30; + var thedate = Math.floor(Date.now() / 1000) + 24 * 60 * 60 * 30; await treasurer.issue(thedate.toString()); -} +}; module.exports = function(deployer, network, accounts) { - if(network == "development"){ - + if (network == "development") { //var apromise = setup(deployer.provider); - deployer.deploy(UniswapFactoryMock) - .then(async () => {await setup()}) + deployer.deploy(UniswapFactoryMock).then(async () => { + await setup(); + }); //return apromise; } From e5101b35d4767d2c5f2664c891c9137af8aba898 Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 22:51:08 +0100 Subject: [PATCH 06/10] refactoring yieldT struct --- contracts/Treasurer.sol | 38 ++-- migrations/4_deploy_uniswap_mocks.js | 13 +- src/utilities.js | 22 +++ test/treasurer.js | 264 +++++++++++++++++++-------- 4 files changed, 227 insertions(+), 110 deletions(-) create mode 100644 src/utilities.js diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index b9879cc..bca4b2c 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -16,12 +16,7 @@ contract Treasurer is Ownable { uint256 debt; // Debt } - struct yieldT { - address where; // contract address of yToken - uint256 when; // maturity time of yToken - } - - mapping(uint256 => yieldT) public yTokens; + mapping(uint256 => yToken) public yTokens; mapping(uint256 => mapping(address => Repo)) public repos; // locked ETH and debt mapping(address => uint256) public unlocked; // unlocked ETH mapping(uint256 => uint256) public settled; // settlement price of collateral @@ -65,13 +60,11 @@ contract Treasurer is Ownable { require(when > now, "treasurer-issue-maturity-is-in-past"); series = totalSeries; require( - yTokens[series].when == 0, + address(yTokens[series]) == address(0), "treasurer-issue-may-not-reissue-series" ); yToken _token = new yToken(when); - address _a = address(_token); - yieldT memory yT = yieldT(_a, when); - yTokens[series] = yT; + yTokens[series] = _token; issuedSeries.push(series); totalSeries = totalSeries + 1; } @@ -123,12 +116,10 @@ contract Treasurer is Ownable { // mint new yTokens // first, ensure yToken is initialized and matures in the future require( - yTokens[series].when > now, + yTokens[series].when() > now, "treasurer-make-invalid-or-matured-ytoken" ); - yToken yT = yToken(yTokens[series].where); - address sender = msg.sender; - yT.mint(sender, made); + yTokens[series].mint(msg.sender, made); } // check that wipe leaves sufficient collateral @@ -172,7 +163,7 @@ contract Treasurer is Ownable { require(series < totalSeries, "treasurer-wipe-unissued-series"); // if yToken has matured, should call resolve require( - now < yTokens[series].when, + now < yTokens[series].when(), "treasurer-wipe-yToken-has-matured" ); @@ -196,12 +187,11 @@ contract Treasurer is Ownable { ); //burn tokens - yToken yT = yToken(yTokens[series].where); require( - yT.balanceOf(msg.sender) > credit, + yTokens[series].balanceOf(msg.sender) > credit, "treasurer-wipe-insufficient-token-balance" ); - yT.burnFrom(msg.sender, credit); + yTokens[series].burnFrom(msg.sender, credit); // reduce the collateral and the debt repo.locked = repo.locked.sub(released); @@ -225,8 +215,7 @@ contract Treasurer is Ownable { require(repo.locked < min, "treasurer-bite-still-safe"); //burn tokens - yToken yT = yToken(yTokens[series].where); - yT.burnByOwner(msg.sender, amount); + yTokens[series].burnByOwner(msg.sender, amount); //update repo uint256 bitten = amount.wmul(minCollateralRatio).wmul(rate); @@ -242,7 +231,7 @@ contract Treasurer is Ownable { function settlement(uint256 series) external { require(series < totalSeries, "treasurer-settlement-unissued-series"); require( - now > yTokens[series].when, + now > yTokens[series].when(), "treasurer-settlement-yToken-hasnt-matured" ); require( @@ -258,7 +247,7 @@ contract Treasurer is Ownable { function withdraw(uint256 series, uint256 amount) external { require(series < totalSeries, "treasurer-withdraw-unissued-series"); require( - now > yTokens[series].when, + now > yTokens[series].when(), "treasurer-withdraw-yToken-hasnt-matured" ); require( @@ -266,8 +255,7 @@ contract Treasurer is Ownable { "treasurer-settlement-settlement-not-yet-called" ); - yToken yT = yToken(yTokens[series].where); - yT.burnByOwner(msg.sender, amount); + yTokens[series].burnByOwner(msg.sender, amount); uint256 rate = settled[series]; uint256 goods = amount.wmul(rate); @@ -279,7 +267,7 @@ contract Treasurer is Ownable { function close(uint256 series) external { require(series < totalSeries, "treasurer-close-unissued-series"); require( - now > yTokens[series].when, + now > yTokens[series].when(), "treasurer-withdraw-yToken-hasnt-matured" ); require( diff --git a/migrations/4_deploy_uniswap_mocks.js b/migrations/4_deploy_uniswap_mocks.js index 8d8a13f..74dbb13 100644 --- a/migrations/4_deploy_uniswap_mocks.js +++ b/migrations/4_deploy_uniswap_mocks.js @@ -1,25 +1,22 @@ const UniswapFactoryMock = artifacts.require("UniswapFactoryMock"); const Treasurer = artifacts.require("Treasurer"); const Oracle = artifacts.require("Oracle"); -const yToken = artifacts.require("yToken"); +const {timestamp} = require("../src/utilities"); -setup = async () => { +setup = async web3 => { let treasurer = await Treasurer.deployed(); let oracle = await Oracle.deployed(); var rate = web3.utils.toWei(".01"); await oracle.set(rate); await treasurer.setOracle(oracle.address); - var thedate = Math.floor(Date.now() / 1000) + 24 * 60 * 60 * 30; - await treasurer.issue(thedate.toString()); + var maturityDate = (await timestamp("latest", web3)) + 24 * 60 * 60 * 30; + await treasurer.issue(maturityDate.toString()); }; module.exports = function(deployer, network, accounts) { if (network == "development") { - //var apromise = setup(deployer.provider); deployer.deploy(UniswapFactoryMock).then(async () => { - await setup(); + await setup(web3); }); - - //return apromise; } }; diff --git a/src/utilities.js b/src/utilities.js new file mode 100644 index 0000000..af2641e --- /dev/null +++ b/src/utilities.js @@ -0,0 +1,22 @@ +const timestamp = (block = "latest", web3) => { + return new Promise((resolve, reject) => { + web3.eth.getBlock(block, false, (err, {timestamp}) => { + if (err) { + return reject(err); + } else { + resolve(timestamp); + } + }); + }); +}; + +// Wait for n blocks to pass +const waitForNSeconds = async function(seconds, web3Provider = web3) { + await send("evm_increaseTime", [seconds], web3Provider); + await send("evm_mine", [], web3Provider); +}; + +module.exports = { + timestamp, + waitForNSeconds +}; diff --git a/test/treasurer.js b/test/treasurer.js index d3b5031..ab0c08f 100644 --- a/test/treasurer.js +++ b/test/treasurer.js @@ -1,23 +1,21 @@ -const Treasurer = artifacts.require('./Treasurer'); -const YToken = artifacts.require('./yToken'); -const MockContract = artifacts.require("./MockContract") -const Oracle= artifacts.require("./Oracle") -const truffleAssert = require('truffle-assertions'); -const helper = require('ganache-time-traveler'); +const Treasurer = artifacts.require("./Treasurer"); +const YToken = artifacts.require("./yToken"); +const MockContract = artifacts.require("./MockContract"); +const Oracle = artifacts.require("./Oracle"); +const truffleAssert = require("truffle-assertions"); +const helper = require("ganache-time-traveler"); var OracleMock = null; const SECONDS_IN_DAY = 86400; -contract('Treasurer', async (accounts) => { - - before('deploy OracleMock', async() => { +contract("Treasurer", async accounts => { + before("deploy OracleMock", async () => { const TreasurerInstance = await Treasurer.deployed(); - OracleMock = await MockContract.new() + OracleMock = await MockContract.new(); await TreasurerInstance.setOracle(OracleMock.address); }); - - it("should refuse to issue a new yToken with old maturity date", async() => { + it("should refuse to issue a new yToken with old maturity date", async () => { const TreasurerInstance = await Treasurer.deployed(); var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; @@ -29,43 +27,55 @@ contract('Treasurer', async (accounts) => { //let series = await TreasurerInstance.issue(currentTimeStamp); }); - - it("should issue a new yToken", async() => { + it("should issue a new yToken", async () => { const TreasurerInstance = await Treasurer.deployed(); var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; var era = currentTimeStamp + SECONDS_IN_DAY; let series = await TreasurerInstance.issue.call(era.toString()); await TreasurerInstance.issue(era.toString()); - let repo = await TreasurerInstance.yTokens(series); - let address = repo.where; + let address = await TreasurerInstance.yTokens(series); var yTokenInstance = await YToken.at(address); - assert.equal(await yTokenInstance.when(), era, "New yToken has incorrect era"); + assert.equal( + await yTokenInstance.when(), + era, + "New yToken has incorrect era" + ); }); - it("should accept collateral", async() => { + it("should accept collateral", async () => { const TreasurerInstance = await Treasurer.deployed(); - await TreasurerInstance.join({from:accounts[1], value:web3.utils.toWei("1")}); + await TreasurerInstance.join({ + from: accounts[1], + value: web3.utils.toWei("1") + }); var result = await TreasurerInstance.unlocked(accounts[1]); - assert.equal(result.toString(), web3.utils.toWei("1"), "Did not accept collateral"); + assert.equal( + result.toString(), + web3.utils.toWei("1"), + "Did not accept collateral" + ); }); - it("should return collateral", async() => { + it("should return collateral", async () => { const TreasurerInstance = await Treasurer.deployed(); - await TreasurerInstance.join({from:accounts[1], value:web3.utils.toWei("1")}); + await TreasurerInstance.join({ + from: accounts[1], + value: web3.utils.toWei("1") + }); var balance_before = await web3.eth.getBalance(accounts[1]); - await TreasurerInstance.exit(web3.utils.toWei("1"), {from:accounts[1]}); + await TreasurerInstance.exit(web3.utils.toWei("1"), {from: accounts[1]}); var balance_after = await web3.eth.getBalance(accounts[1]); assert(balance_after > balance_before); }); - it("should provide Oracle address", async() => { + it("should provide Oracle address", async () => { const TreasurerInstance = await Treasurer.deployed(); - const _address = await TreasurerInstance.oracle() + const _address = await TreasurerInstance.oracle(); assert.equal(_address, OracleMock.address); }); - it("should make new yTokens", async() => { + it("should make new yTokens", async () => { const TreasurerInstance = await Treasurer.deployed(); // create another yToken series with a 24 hour period until maturity @@ -81,21 +91,38 @@ contract('Treasurer', async (accounts) => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE // make new yTokens - await TreasurerInstance.make(series, web3.utils.toWei("1"), web3.utils.toWei("1"), {from:accounts[1]}); + await TreasurerInstance.make( + series, + web3.utils.toWei("1"), + web3.utils.toWei("1"), + {from: accounts[1]} + ); // check yToken balance const token = await TreasurerInstance.yTokens.call(series); - const yTokenInstance = await YToken.at(token.where); + const yTokenInstance = await YToken.at(token); const balance = await yTokenInstance.balanceOf(accounts[1]); - assert.equal(balance.toString(), web3.utils.toWei("1"), "Did not make new yTokens"); + assert.equal( + balance.toString(), + web3.utils.toWei("1"), + "Did not make new yTokens" + ); //check unlocked collateral, locked collateral const repo = await TreasurerInstance.repos(series, accounts[1]); - assert.equal(repo.locked.toString(), web3.utils.toWei("1"), "Did not lock collateral"); - assert.equal(repo.debt.toString(), web3.utils.toWei("1"), "Did not create debt"); + assert.equal( + repo.locked.toString(), + web3.utils.toWei("1"), + "Did not lock collateral" + ); + assert.equal( + repo.debt.toString(), + web3.utils.toWei("1"), + "Did not create debt" + ); }); - it("should accept tokens to wipe yToken debt", async() => { + it("should accept tokens to wipe yToken debt", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; var amountToWipe = web3.utils.toWei(".1"); @@ -107,21 +134,37 @@ contract('Treasurer', async (accounts) => { // get acess to token const token = await TreasurerInstance.yTokens.call(series); - const yTokenInstance = await YToken.at(token.where); + const yTokenInstance = await YToken.at(token); //authorize the wipe - await yTokenInstance.approve(TreasurerInstance.address, amountToWipe, {from:accounts[1]}); + await yTokenInstance.approve(TreasurerInstance.address, amountToWipe, { + from: accounts[1] + }); // wipe tokens - await TreasurerInstance.wipe(series, amountToWipe, web3.utils.toWei(".1"), {from:accounts[1]}); + await TreasurerInstance.wipe(series, amountToWipe, web3.utils.toWei(".1"), { + from: accounts[1] + }); // check yToken balance const balance = await yTokenInstance.balanceOf(accounts[1]); - assert.equal(balance.toString(), web3.utils.toWei(".9"), "Did not wipe yTokens"); + assert.equal( + balance.toString(), + web3.utils.toWei(".9"), + "Did not wipe yTokens" + ); //check unlocked collateral, locked collateral const repo = await TreasurerInstance.repos(series, accounts[1]); - assert.equal(repo.locked.toString(), web3.utils.toWei(".9"), "Did not unlock collateral"); - assert.equal(repo.debt.toString(), web3.utils.toWei(".9"), "Did not wipe debg"); + assert.equal( + repo.locked.toString(), + web3.utils.toWei(".9"), + "Did not unlock collateral" + ); + assert.equal( + repo.debt.toString(), + web3.utils.toWei(".9"), + "Did not wipe debg" + ); }); /******** No longer relevant, but saved as an example @@ -139,7 +182,7 @@ contract('Treasurer', async (accounts) => { }); *****/ - it("should refuse to create an undercollateralized repos", async() => { + it("should refuse to create an undercollateralized repos", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; @@ -151,15 +194,22 @@ contract('Treasurer', async (accounts) => { // make new yTokens with new account // at 100 dai/ETH, and 150% collateral requirement (set at deployment), // should refuse to create 101 yTokens - await TreasurerInstance.join({from:accounts[2], value:web3.utils.toWei("1.5")}); + await TreasurerInstance.join({ + from: accounts[2], + value: web3.utils.toWei("1.5") + }); await truffleAssert.fails( - TreasurerInstance.make(series, web3.utils.toWei("101"), web3.utils.toWei("1.5"), {from:accounts[2]}), - truffleAssert.REVERT + TreasurerInstance.make( + series, + web3.utils.toWei("101"), + web3.utils.toWei("1.5"), + {from: accounts[2]} + ), + truffleAssert.REVERT ); - }); - it("should accept liquidations undercollateralized repos", async() => { + it("should accept liquidations undercollateralized repos", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; @@ -169,46 +219,79 @@ contract('Treasurer', async (accounts) => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE // make new yTokens with new account - await TreasurerInstance.make(series, web3.utils.toWei("100"), web3.utils.toWei("1.5"), {from:accounts[2]}); + await TreasurerInstance.make( + series, + web3.utils.toWei("100"), + web3.utils.toWei("1.5"), + {from: accounts[2]} + ); // transfer tokens to another account const token = await TreasurerInstance.yTokens.call(series); - const yTokenInstance = await YToken.at(token.where); - await yTokenInstance.transfer(accounts[3], web3.utils.toWei("100"), {from:accounts[2]}); + const yTokenInstance = await YToken.at(token); + await yTokenInstance.transfer(accounts[3], web3.utils.toWei("100"), { + from: accounts[2] + }); //change rate to make tokens undercollateralized rate = web3.utils.toWei(".02"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); await truffleAssert.fails( - TreasurerInstance.wipe(series, web3.utils.toWei("100"), web3.utils.toWei("0"), {from:accounts[2]}), - truffleAssert.REVERT, - "treasurer-wipe-insufficient-token-balance" + TreasurerInstance.wipe( + series, + web3.utils.toWei("100"), + web3.utils.toWei("0"), + {from: accounts[2]} + ), + truffleAssert.REVERT, + "treasurer-wipe-insufficient-token-balance" ); var balance_before = await web3.eth.getBalance(accounts[3]); // attempt to liquidate - const result = await TreasurerInstance.liquidate(series, accounts[2], web3.utils.toWei("50"), {from:accounts[3]}); + const result = await TreasurerInstance.liquidate( + series, + accounts[2], + web3.utils.toWei("50"), + {from: accounts[3]} + ); //check received 1.05 const tx = await web3.eth.getTransaction(result.tx); var balance_after = await web3.eth.getBalance(accounts[3]); - const total = Number(balance_after) - Number(balance_before) + result.receipt.gasUsed * tx.gasPrice; + const total = + Number(balance_after) - + Number(balance_before) + + result.receipt.gasUsed * tx.gasPrice; //try to constrain the test rather than use an inequality (I think the Javascript math is losing precision) - assert(total > Number(web3.utils.toWei("1.04999")), "liquidation funds not received"); - assert(total < Number(web3.utils.toWei("1.05001")), "liquidation funds not received"); + assert( + total > Number(web3.utils.toWei("1.04999")), + "liquidation funds not received" + ); + assert( + total < Number(web3.utils.toWei("1.05001")), + "liquidation funds not received" + ); //check unlocked collateral, locked collateral const repo = await TreasurerInstance.repos(series, accounts[2]); - assert.equal(repo.locked.toString(), web3.utils.toWei(".45"), "Did not unlock collateral"); - assert.equal(repo.debt.toString(), web3.utils.toWei("50"), "Did not wipe debg"); - + assert.equal( + repo.locked.toString(), + web3.utils.toWei(".45"), + "Did not unlock collateral" + ); + assert.equal( + repo.debt.toString(), + web3.utils.toWei("50"), + "Did not wipe debg" + ); }); - it("should allow for settlement", async() => { + it("should allow for settlement", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; snapShot = await helper.takeSnapshot(); - snapshotId = snapShot['result']; + snapshotId = snapShot["result"]; await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); @@ -218,56 +301,83 @@ contract('Treasurer', async (accounts) => { await helper.revertToSnapshot(snapshotId); }); - it("should allow token holder to withdraw face value", async() => { + it("should allow token holder to withdraw face value", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; snapShot = await helper.takeSnapshot(); - snapshotId = snapShot['result']; + snapshotId = snapShot["result"]; await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); var balance_before = await web3.eth.getBalance(accounts[3]); - const result = await TreasurerInstance.withdraw(series, web3.utils.toWei("25"), {from:accounts[3]}); + const result = await TreasurerInstance.withdraw( + series, + web3.utils.toWei("25"), + {from: accounts[3]} + ); var balance_after = await web3.eth.getBalance(accounts[3]); const tx = await web3.eth.getTransaction(result.tx); - const total = Number(balance_after) - Number(balance_before) + result.receipt.gasUsed * tx.gasPrice; - assert(total > Number(web3.utils.toWei(".49999")), "withdrawn funds not received"); - assert(total < Number(web3.utils.toWei(".50001")), "withdrawn funds not received"); + const total = + Number(balance_after) - + Number(balance_before) + + result.receipt.gasUsed * tx.gasPrice; + assert( + total > Number(web3.utils.toWei(".49999")), + "withdrawn funds not received" + ); + assert( + total < Number(web3.utils.toWei(".50001")), + "withdrawn funds not received" + ); //assert.equal(rate, web3.utils.toWei(".02"), "settled rate not set"); //unwind state await helper.revertToSnapshot(snapshotId); }); - it("should allow repo holder to close repo and recieve remaining collateral", async() => { + it("should allow repo holder to close repo and recieve remaining collateral", async () => { const TreasurerInstance = await Treasurer.deployed(); var series = 2; snapShot = await helper.takeSnapshot(); - snapshotId = snapShot['result']; + snapshotId = snapShot["result"]; //fix margin for account 2 (it is underfunded from wipe test) - await TreasurerInstance.join({from:accounts[2], value:web3.utils.toWei("1")}); - await TreasurerInstance.make(series, web3.utils.toWei("0"), web3.utils.toWei("1"), {from:accounts[2]}), - - await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); + await TreasurerInstance.join({ + from: accounts[2], + value: web3.utils.toWei("1") + }); + await TreasurerInstance.make( + series, + web3.utils.toWei("0"), + web3.utils.toWei("1"), + {from: accounts[2]} + ), + await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); var balance_before = await web3.eth.getBalance(accounts[2]); //run close - const result = await TreasurerInstance.close(series, {from:accounts[2]}); + const result = await TreasurerInstance.close(series, {from: accounts[2]}); var balance_after = await web3.eth.getBalance(accounts[2]); const tx = await web3.eth.getTransaction(result.tx); var balance_after = await web3.eth.getBalance(accounts[2]); - const total = Number(balance_after) - Number(balance_before) + result.receipt.gasUsed * tx.gasPrice; - assert(total > Number(web3.utils.toWei(".44999")), "repo funds not received"); - assert(total < Number(web3.utils.toWei(".45001")), "repo funds not received"); + const total = + Number(balance_after) - + Number(balance_before) + + result.receipt.gasUsed * tx.gasPrice; + assert( + total > Number(web3.utils.toWei(".44999")), + "repo funds not received" + ); + assert( + total < Number(web3.utils.toWei(".45001")), + "repo funds not received" + ); //unwind state await helper.revertToSnapshot(snapshotId); - }); - }); From ddf45d1fa62780c9544632ba9fa0d778d8d43b12 Mon Sep 17 00:00:00 2001 From: josojo Date: Fri, 22 Nov 2019 23:09:29 +0100 Subject: [PATCH 07/10] renaming for easier readability --- contracts/Treasurer.sol | 90 +++++++++++++++++++---------------------- contracts/yToken.sol | 6 +-- test/treasurer.js | 22 +++++----- 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index bca4b2c..04fb6b9 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -11,13 +11,12 @@ contract Treasurer is Ownable { using ExponentialOperations for uint256; struct Repo { - uint256 locked; // Locked Collateral - uint256 unminted; // unminted - uint256 debt; // Debt + uint256 lockedCollateralAmount; + uint256 debtAmount; } mapping(uint256 => yToken) public yTokens; - mapping(uint256 => mapping(address => Repo)) public repos; // locked ETH and debt + mapping(uint256 => mapping(address => Repo)) public repos; // lockedCollateralAmount ETH and debtAmount mapping(address => uint256) public unlocked; // unlocked ETH mapping(uint256 => uint256) public settled; // settlement price of collateral uint256[] public issuedSeries; @@ -34,13 +33,6 @@ contract Treasurer is Ownable { minCollateralRatio = minCollateralRatio_; } - // --- Views --- - - // return unlocked collateral balance - function balance(address usr) public view returns (uint256) { - return unlocked[usr]; - } - // --- Actions --- // provide address to oracle @@ -56,14 +48,14 @@ contract Treasurer is Ownable { } // issue new yToken - function issue(uint256 when) external onlyOwner returns (uint256 series) { - require(when > now, "treasurer-issue-maturity-is-in-past"); + function issue(uint256 maturityTime) external returns (uint256 series) { + require(maturityTime > now, "treasurer-issue-maturity-is-in-past"); series = totalSeries; require( address(yTokens[series]) == address(0), "treasurer-issue-may-not-reissue-series" ); - yToken _token = new yToken(when); + yToken _token = new yToken(maturityTime); yTokens[series] = _token; issuedSeries.push(series); totalSeries = totalSeries + 1; @@ -107,16 +99,16 @@ contract Treasurer is Ownable { "treasurer-make-insufficient-collateral-for-those-tokens" ); - // lock msg.sender Collateral, add debt + // lock msg.sender Collateral, add debtAmount unlocked[msg.sender] = unlocked[msg.sender].sub(paid); - repo.locked = repo.locked.add(paid); - repo.debt = repo.debt.add(made); + repo.lockedCollateralAmount = repo.lockedCollateralAmount.add(paid); + repo.debtAmount = repo.debtAmount.add(made); repos[series][msg.sender] = repo; // mint new yTokens // first, ensure yToken is initialized and matures in the future require( - yTokens[series].when() > now, + yTokens[series].maturityTime() > now, "treasurer-make-invalid-or-matured-ytoken" ); yTokens[series].mint(msg.sender, made); @@ -136,16 +128,16 @@ contract Treasurer is Ownable { require(series < totalSeries, "treasurer-wipeCheck-unissued-series"); Repo memory repo = repos[series][msg.sender]; require( - repo.locked >= released, + repo.lockedCollateralAmount >= released, "treasurer-wipe-release-more-than-locked" ); require( - repo.debt >= credit, - "treasurer-wipe-wipe-more-debt-than-present" + repo.debtAmount >= credit, + "treasurer-wipe-wipe-more-debtAmount-than-present" ); // if would be undercollateralized after freeing clean, fail - uint256 rlocked = repo.locked.sub(released); - uint256 rdebt = repo.debt.sub(credit); + uint256 rlocked = repo.lockedCollateralAmount.sub(released); + uint256 rdebt = repo.debtAmount.sub(credit); uint256 rate = peek(); // to add rate getter!!! uint256 min = rdebt.wmul(collateralRatio).wmul(rate); uint256 deficiency = 0; @@ -155,7 +147,7 @@ contract Treasurer is Ownable { return (rlocked >= min, deficiency); } - // wipe repo debt with yToken + // wipe repo debtAmount with yToken // series - yToken to mint // credit - amount of yToken to wipe // released - amount of collateral to free @@ -163,22 +155,22 @@ contract Treasurer is Ownable { require(series < totalSeries, "treasurer-wipe-unissued-series"); // if yToken has matured, should call resolve require( - now < yTokens[series].when(), + now < yTokens[series].maturityTime(), "treasurer-wipe-yToken-has-matured" ); Repo memory repo = repos[series][msg.sender]; require( - repo.locked >= released, + repo.lockedCollateralAmount >= released, "treasurer-wipe-release-more-than-locked" ); require( - repo.debt >= credit, - "treasurer-wipe-wipe-more-debt-than-present" + repo.debtAmount >= credit, + "treasurer-wipe-wipe-more-debtAmount-than-present" ); // if would be undercollateralized after freeing clean, fail - uint256 rlocked = repo.locked.sub(released); - uint256 rdebt = repo.debt.sub(credit); + uint256 rlocked = repo.lockedCollateralAmount.sub(released); + uint256 rdebt = repo.debtAmount.sub(credit); uint256 rate = peek(); // to add rate getter!!! uint256 min = rdebt.wmul(collateralRatio).wmul(rate); require( @@ -193,9 +185,9 @@ contract Treasurer is Ownable { ); yTokens[series].burnFrom(msg.sender, credit); - // reduce the collateral and the debt - repo.locked = repo.locked.sub(released); - repo.debt = repo.debt.sub(credit); + // reduce the collateral and the debtAmount + repo.lockedCollateralAmount = repo.lockedCollateralAmount.sub(released); + repo.debtAmount = repo.debtAmount.sub(credit); repos[series][msg.sender] = repo; // add collateral back to the unlocked @@ -203,35 +195,35 @@ contract Treasurer is Ownable { } // liquidate a repo - // series - yToken of debt to buy + // series - yToken of debtAmount to buy // bum - owner of the undercollateralized repo - // amount - amount of yToken debt to buy + // amount - amount of yToken debtAmount to buy function liquidate(uint256 series, address bum, uint256 amount) external { require(series < totalSeries, "treasurer-liquidate-unissued-series"); //check that repo is in danger zone Repo memory repo = repos[series][bum]; uint256 rate = peek(); // to add rate getter!!! - uint256 min = repo.debt.wmul(minCollateralRatio).wmul(rate); - require(repo.locked < min, "treasurer-bite-still-safe"); + uint256 min = repo.debtAmount.wmul(minCollateralRatio).wmul(rate); + require(repo.lockedCollateralAmount < min, "treasurer-bite-still-safe"); //burn tokens yTokens[series].burnByOwner(msg.sender, amount); //update repo uint256 bitten = amount.wmul(minCollateralRatio).wmul(rate); - repo.locked = repo.locked.sub(bitten); - repo.debt = repo.debt.sub(amount); + repo.lockedCollateralAmount = repo.lockedCollateralAmount.sub(bitten); + repo.debtAmount = repo.debtAmount.sub(amount); repos[series][bum] = repo; // send bitten funds msg.sender.transfer(bitten); } // trigger settlement - // series - yToken of debt to settle + // series - yToken of debtAmount to settle function settlement(uint256 series) external { require(series < totalSeries, "treasurer-settlement-unissued-series"); require( - now > yTokens[series].when(), + now > yTokens[series].maturityTime(), "treasurer-settlement-yToken-hasnt-matured" ); require( @@ -247,7 +239,7 @@ contract Treasurer is Ownable { function withdraw(uint256 series, uint256 amount) external { require(series < totalSeries, "treasurer-withdraw-unissued-series"); require( - now > yTokens[series].when(), + now > yTokens[series].maturityTime(), "treasurer-withdraw-yToken-hasnt-matured" ); require( @@ -267,7 +259,7 @@ contract Treasurer is Ownable { function close(uint256 series) external { require(series < totalSeries, "treasurer-close-unissued-series"); require( - now > yTokens[series].when(), + now > yTokens[series].maturityTime(), "treasurer-withdraw-yToken-hasnt-matured" ); require( @@ -277,15 +269,17 @@ contract Treasurer is Ownable { Repo memory repo = repos[series][msg.sender]; uint256 rate = settled[series]; // to add rate getter!!! - uint256 remainder = repo.debt.wmul(rate); + uint256 remainder = repo.debtAmount.wmul(rate); require( - repo.locked > remainder, + repo.lockedCollateralAmount > remainder, "treasurer-settlement-repo-underfunded-at-settlement" ); - uint256 goods = repo.locked.sub(repo.debt.wmul(rate)); - repo.locked = 0; - repo.debt = 0; + uint256 goods = repo.lockedCollateralAmount.sub( + repo.debtAmount.wmul(rate) + ); + repo.lockedCollateralAmount = 0; + repo.debtAmount = 0; repos[series][msg.sender] = repo; msg.sender.transfer(goods); diff --git a/contracts/yToken.sol b/contracts/yToken.sol index 8b3d073..70c9622 100644 --- a/contracts/yToken.sol +++ b/contracts/yToken.sol @@ -4,10 +4,10 @@ import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol"; contract yToken is ERC20Burnable, ERC20Mintable { - uint256 public when; + uint256 public maturityTime; - constructor(uint256 when_) public { - when = when_; + constructor(uint256 maturityTime_) public { + maturityTime = maturityTime_; } function burnByOwner(address account, uint256 amount) external onlyMinter { diff --git a/test/treasurer.js b/test/treasurer.js index ab0c08f..0eacb0f 100644 --- a/test/treasurer.js +++ b/test/treasurer.js @@ -37,7 +37,7 @@ contract("Treasurer", async accounts => { let address = await TreasurerInstance.yTokens(series); var yTokenInstance = await YToken.at(address); assert.equal( - await yTokenInstance.when(), + await yTokenInstance.maturityTime(), era, "New yToken has incorrect era" ); @@ -108,17 +108,17 @@ contract("Treasurer", async accounts => { "Did not make new yTokens" ); - //check unlocked collateral, locked collateral + //check unlocked collateral, lockedCollateralAmount collateral const repo = await TreasurerInstance.repos(series, accounts[1]); assert.equal( - repo.locked.toString(), + repo.lockedCollateralAmount.toString(), web3.utils.toWei("1"), "Did not lock collateral" ); assert.equal( - repo.debt.toString(), + repo.debtAmount.toString(), web3.utils.toWei("1"), - "Did not create debt" + "Did not create debtAmount" ); }); @@ -153,15 +153,15 @@ contract("Treasurer", async accounts => { "Did not wipe yTokens" ); - //check unlocked collateral, locked collateral + //check unlocked collateral, lockedCollateralAmount collateral const repo = await TreasurerInstance.repos(series, accounts[1]); assert.equal( - repo.locked.toString(), + repo.lockedCollateralAmount.toString(), web3.utils.toWei(".9"), "Did not unlock collateral" ); assert.equal( - repo.debt.toString(), + repo.debtAmount.toString(), web3.utils.toWei(".9"), "Did not wipe debg" ); @@ -273,15 +273,15 @@ contract("Treasurer", async accounts => { "liquidation funds not received" ); - //check unlocked collateral, locked collateral + //check unlocked collateral, lockedCollateralAmount collateral const repo = await TreasurerInstance.repos(series, accounts[2]); assert.equal( - repo.locked.toString(), + repo.lockedCollateralAmount.toString(), web3.utils.toWei(".45"), "Did not unlock collateral" ); assert.equal( - repo.debt.toString(), + repo.debtAmount.toString(), web3.utils.toWei("50"), "Did not wipe debg" ); From 147cb003b0ff640df5c1f18d1540241d021a9896 Mon Sep 17 00:00:00 2001 From: josojo Date: Sat, 23 Nov 2019 00:48:40 +0100 Subject: [PATCH 08/10] adding linting, refactor oracle usage, make tests independent --- .eslintrc | 80 ++++++++++++++++++++ .eslintrc.js | 29 ++++++++ contracts/Treasurer.sol | 24 +++--- package.json | 3 +- test/.eslintrc | 10 +++ test/treasurer.js | 159 ++++++++++++++++++++++++++-------------- 6 files changed, 241 insertions(+), 64 deletions(-) create mode 100644 .eslintrc create mode 100644 .eslintrc.js create mode 100644 test/.eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c92544a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,80 @@ +{ + "extends": ["airbnb"], + "parser": "babel-eslint", + "plugins": ["jest"], + "settings": { + "import/resolver": { + "webpack": { + "config": "webpack.dev.config.js" + } + }, + "import/extensions": [".js", ".jsx"], + "import/ignore": ["\\.(s?css|less|styl|svg|json)$"] + }, + "rules": { + "import/no-unresolved": [ + 2, + { + "commonjs": true, + "amd": true, + "caseSensitive": true + } + ], + "import/named": 2, + "import/default": 2, + "import/namespace": 2, + "react/jsx-filename-extension": [ + 1, + { + "extensions": [".js", ".jsx"] + } + ], + "react/forbid-prop-types": [ + 1, + { + "forbid": ["object", "any"] + } + ], + "class-methods-use-this": 0, + "one-var": 0, + "one-var-declaration-per-line": 0, + "no-nested-ternary": 0, + "no-await-in-loop": 0, + "no-multi-assign": 0, + "object-curly-newline": 0, + "no-param-reassign": 0, + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": true, + "optionalDependencies": false, + "peerDependencies": false + } + ], + "semi": ["error", "never"], + "max-len": [ + "error", + 120, + 2, + { + "ignoreUrls": true, + "ignoreComments": false, + "ignoreRegExpLiterals": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true + } + ], + "no-restricted-syntax": ["error", "WithStatement"] + }, + "env": { + "jest/globals": true, + "browser": true, + "mocha": true + }, + "globals": { + "assert": true, + "contract": true, + "artifacts": true, + "web3": true + } +} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..e10a50d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,29 @@ +module.exports = { + env: { + browser: true, + commonjs: true, + es6: true + }, + extends: "eslint:recommended", + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 2018 + }, + plugins: ["react"], + rules: { + indent: ["error", 2], + "linebreak-style": ["error", "unix"], + quotes: ["error", "double"], + semi: ["error", "never"], + "prefer-const": ["error"], + "no-var": ["error"] + }, + globals: { + artifacts: false, + contract: false, + assert: false, + web3: false + } +}; diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 04fb6b9..ceec95a 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -20,7 +20,7 @@ contract Treasurer is Ownable { mapping(address => uint256) public unlocked; // unlocked ETH mapping(uint256 => uint256) public settled; // settlement price of collateral uint256[] public issuedSeries; - address public oracle; + Oracle public oracle; uint256 public collateralRatio; // collateralization ratio uint256 public minCollateralRatio; // minimum collateralization ratio uint256 public totalSeries = 0; @@ -37,14 +37,18 @@ contract Treasurer is Ownable { // provide address to oracle // oracle_ - address of the oracle contract - function setOracle(address oracle_) external onlyOwner { + function setOracle(Oracle oracle_) external onlyOwner { + require(address(oracle) == address(0), "oracle was already set"); oracle = oracle_; } // get oracle value - function peek() public view returns (uint256 r) { - Oracle _oracle = Oracle(oracle); - r = _oracle.read(); + function getSettlmentVSCollateralTokenRate() + public + view + returns (uint256 r) + { + r = oracle.read(); } // issue new yToken @@ -92,7 +96,7 @@ contract Treasurer is Ownable { ); Repo memory repo = repos[series][msg.sender]; - uint256 rate = peek(); // to add rate getter!!! + uint256 rate = getSettlmentVSCollateralTokenRate(); // to add rate getter!!! uint256 min = made.wmul(collateralRatio).wmul(rate); require( paid >= min, @@ -138,7 +142,7 @@ contract Treasurer is Ownable { // if would be undercollateralized after freeing clean, fail uint256 rlocked = repo.lockedCollateralAmount.sub(released); uint256 rdebt = repo.debtAmount.sub(credit); - uint256 rate = peek(); // to add rate getter!!! + uint256 rate = getSettlmentVSCollateralTokenRate(); // to add rate getter!!! uint256 min = rdebt.wmul(collateralRatio).wmul(rate); uint256 deficiency = 0; if (min >= rlocked) { @@ -171,7 +175,7 @@ contract Treasurer is Ownable { // if would be undercollateralized after freeing clean, fail uint256 rlocked = repo.lockedCollateralAmount.sub(released); uint256 rdebt = repo.debtAmount.sub(credit); - uint256 rate = peek(); // to add rate getter!!! + uint256 rate = getSettlmentVSCollateralTokenRate(); // to add rate getter!!! uint256 min = rdebt.wmul(collateralRatio).wmul(rate); require( rlocked >= min, @@ -202,7 +206,7 @@ contract Treasurer is Ownable { require(series < totalSeries, "treasurer-liquidate-unissued-series"); //check that repo is in danger zone Repo memory repo = repos[series][bum]; - uint256 rate = peek(); // to add rate getter!!! + uint256 rate = getSettlmentVSCollateralTokenRate(); // to add rate getter!!! uint256 min = repo.debtAmount.wmul(minCollateralRatio).wmul(rate); require(repo.lockedCollateralAmount < min, "treasurer-bite-still-safe"); @@ -230,7 +234,7 @@ contract Treasurer is Ownable { settled[series] == 0, "treasurer-settlement-settlement-already-called" ); - settled[series] = peek(); + settled[series] = getSettlmentVSCollateralTokenRate(); } // redeem tokens for underlying Ether diff --git a/package.json b/package.json index dcdd7a2..44286d1 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "test": "test" }, "scripts": { + "lint": "./node_modules/.bin/eslint .", "test": "echo \"Error: no test specified\" && exit 1", - "prettier:solidity": "./node_modules/.bin/prettier --write 'contracts/**/*.sol'" + "prettier": "./node_modules/.bin/prettier --write 'contracts/**/*.sol'" }, "keywords": [], "author": "", diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000..0f5b6bc --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,10 @@ +{ + "env": { + "mocha": true, + "node": true + }, + "plugins": ["no-only-tests"], + "rules": { + "no-only-tests/no-only-tests": "error" + } +} diff --git a/test/treasurer.js b/test/treasurer.js index 0eacb0f..42449ea 100644 --- a/test/treasurer.js +++ b/test/treasurer.js @@ -4,19 +4,24 @@ const MockContract = artifacts.require("./MockContract"); const Oracle = artifacts.require("./Oracle"); const truffleAssert = require("truffle-assertions"); const helper = require("ganache-time-traveler"); - +const {timestamp} = require("./../src/utilities"); var OracleMock = null; const SECONDS_IN_DAY = 86400; contract("Treasurer", async accounts => { - before("deploy OracleMock", async () => { - const TreasurerInstance = await Treasurer.deployed(); + const collateralRatio = web3.utils.toWei("1.5"); + const minCollateralRatio = web3.utils.toWei("1.05"); + let TreasurerInstance; + beforeEach("deploy OracleMock", async () => { + TreasurerInstance = await Treasurer.new( + collateralRatio, + minCollateralRatio + ); OracleMock = await MockContract.new(); await TreasurerInstance.setOracle(OracleMock.address); }); it("should refuse to issue a new yToken with old maturity date", async () => { - const TreasurerInstance = await Treasurer.deployed(); var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; currentTimeStamp = currentTimeStamp - 1; @@ -28,7 +33,6 @@ contract("Treasurer", async accounts => { }); it("should issue a new yToken", async () => { - const TreasurerInstance = await Treasurer.deployed(); var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; var era = currentTimeStamp + SECONDS_IN_DAY; @@ -44,7 +48,6 @@ contract("Treasurer", async accounts => { }); it("should accept collateral", async () => { - const TreasurerInstance = await Treasurer.deployed(); await TreasurerInstance.join({ from: accounts[1], value: web3.utils.toWei("1") @@ -58,7 +61,6 @@ contract("Treasurer", async accounts => { }); it("should return collateral", async () => { - const TreasurerInstance = await Treasurer.deployed(); await TreasurerInstance.join({ from: accounts[1], value: web3.utils.toWei("1") @@ -70,21 +72,22 @@ contract("Treasurer", async accounts => { }); it("should provide Oracle address", async () => { - const TreasurerInstance = await Treasurer.deployed(); const _address = await TreasurerInstance.oracle(); assert.equal(_address, OracleMock.address); }); it("should make new yTokens", async () => { - const TreasurerInstance = await Treasurer.deployed(); - // create another yToken series with a 24 hour period until maturity var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; - var series = 2; + var series = 0; var era = currentTimeStamp + SECONDS_IN_DAY; await TreasurerInstance.issue(era); - + //funding + await TreasurerInstance.join({ + from: accounts[1], + value: web3.utils.toWei("1") + }); // set up oracle const oracle = await Oracle.new(); var rate = web3.utils.toWei(".01"); // rate = Dai/ETH @@ -123,15 +126,31 @@ contract("Treasurer", async accounts => { }); it("should accept tokens to wipe yToken debt", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; var amountToWipe = web3.utils.toWei(".1"); + var currentTimeStamp = await timestamp("latest", web3); + var series = 0; + var era = currentTimeStamp + SECONDS_IN_DAY; + await TreasurerInstance.issue(era); + + //funding + await TreasurerInstance.join({ + from: accounts[1], + value: web3.utils.toWei("1") + }); // set up oracle const oracle = await Oracle.new(); var rate = web3.utils.toWei(".01"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE + // make new yTokens + await TreasurerInstance.make( + series, + web3.utils.toWei("1"), + web3.utils.toWei("1"), + {from: accounts[1]} + ); + // get acess to token const token = await TreasurerInstance.yTokens.call(series); const yTokenInstance = await YToken.at(token); @@ -183,8 +202,7 @@ contract("Treasurer", async accounts => { *****/ it("should refuse to create an undercollateralized repos", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; + var series = 0; // set up oracle const oracle = await Oracle.new(); @@ -210,14 +228,20 @@ contract("Treasurer", async accounts => { }); it("should accept liquidations undercollateralized repos", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; + var series = 0; + var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; + await TreasurerInstance.issue(era); // set up oracle const oracle = await Oracle.new(); var rate = web3.utils.toWei(".01"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE + //fund account + await TreasurerInstance.join({ + from: accounts[2], + value: web3.utils.toWei("1.5") + }); // make new yTokens with new account await TreasurerInstance.make( series, @@ -288,73 +312,105 @@ contract("Treasurer", async accounts => { }); it("should allow for settlement", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; - snapShot = await helper.takeSnapshot(); - snapshotId = snapShot["result"]; + var series = 0; + var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; + await TreasurerInstance.issue(era); + + // set up oracle + const oracle = await Oracle.new(); + var rate = web3.utils.toWei(".01"); // rate = Dai/ETH + await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE + + //fund account + await TreasurerInstance.join({ + from: accounts[2], + value: web3.utils.toWei("1.5") + }); + // make new yTokens with new account + await TreasurerInstance.make( + series, + web3.utils.toWei("100"), + web3.utils.toWei("1.5"), + {from: accounts[2]} + ); await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); var rate = (await TreasurerInstance.settled(series)).toString(); - assert.equal(rate, web3.utils.toWei(".02"), "settled rate not set"); - //unwind state - await helper.revertToSnapshot(snapshotId); + assert.equal(rate, web3.utils.toWei(".01"), "settled rate not set"); }); it("should allow token holder to withdraw face value", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; - snapShot = await helper.takeSnapshot(); - snapshotId = snapShot["result"]; + var series = 0; + var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; + await TreasurerInstance.issue(era); + + // set up oracle + const oracle = await Oracle.new(); + var rate = web3.utils.toWei(".01"); // rate = Dai/ETH + await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE + //fund account + await TreasurerInstance.join({ + from: accounts[2], + value: web3.utils.toWei("1.5") + }); + // make new yTokens with new account + await TreasurerInstance.make( + series, + web3.utils.toWei("100"), + web3.utils.toWei("1.5"), + {from: accounts[2]} + ); await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); - var balance_before = await web3.eth.getBalance(accounts[3]); + var balance_before = await web3.eth.getBalance(accounts[2]); const result = await TreasurerInstance.withdraw( series, web3.utils.toWei("25"), - {from: accounts[3]} + {from: accounts[2]} ); - var balance_after = await web3.eth.getBalance(accounts[3]); + var balance_after = await web3.eth.getBalance(accounts[2]); const tx = await web3.eth.getTransaction(result.tx); const total = Number(balance_after) - Number(balance_before) + result.receipt.gasUsed * tx.gasPrice; assert( - total > Number(web3.utils.toWei(".49999")), + total > Number(web3.utils.toWei(".24999")), "withdrawn funds not received" ); assert( - total < Number(web3.utils.toWei(".50001")), + total < Number(web3.utils.toWei(".250001")), "withdrawn funds not received" ); - - //assert.equal(rate, web3.utils.toWei(".02"), "settled rate not set"); - //unwind state - await helper.revertToSnapshot(snapshotId); }); it("should allow repo holder to close repo and recieve remaining collateral", async () => { - const TreasurerInstance = await Treasurer.deployed(); - var series = 2; - snapShot = await helper.takeSnapshot(); - snapshotId = snapShot["result"]; + var series = 0; + var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; + await TreasurerInstance.issue(era); + + // set up oracle + const oracle = await Oracle.new(); + var rate = web3.utils.toWei(".01"); // rate = Dai/ETH + await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE - //fix margin for account 2 (it is underfunded from wipe test) + //fund account await TreasurerInstance.join({ from: accounts[2], - value: web3.utils.toWei("1") + value: web3.utils.toWei("1.5") }); + // make new yTokens with new account await TreasurerInstance.make( series, - web3.utils.toWei("0"), - web3.utils.toWei("1"), + web3.utils.toWei("100"), + web3.utils.toWei("1.5"), {from: accounts[2]} - ), - await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); + ); + await helper.advanceTimeAndBlock(SECONDS_IN_DAY * 1.5); await TreasurerInstance.settlement(series); var balance_before = await web3.eth.getBalance(accounts[2]); @@ -369,15 +425,12 @@ contract("Treasurer", async accounts => { Number(balance_before) + result.receipt.gasUsed * tx.gasPrice; assert( - total > Number(web3.utils.toWei(".44999")), + total > Number(web3.utils.toWei(".4999")), "repo funds not received" ); assert( - total < Number(web3.utils.toWei(".45001")), + total < Number(web3.utils.toWei(".5001")), "repo funds not received" ); - - //unwind state - await helper.revertToSnapshot(snapshotId); }); }); From 9e53a2d82a5e24d03e47b910e81e66559a7be3c6 Mon Sep 17 00:00:00 2001 From: josojo Date: Sat, 23 Nov 2019 15:00:56 +0100 Subject: [PATCH 09/10] quite some renaming --- README.md | 10 ++-- contracts/Treasurer.sol | 26 ++++++---- migrations/4_deploy_uniswap_mocks.js | 2 +- test/treasurer.js | 78 ++++++++++++++-------------- 4 files changed, 61 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 14be78a..77878b9 100644 --- a/README.md +++ b/README.md @@ -20,20 +20,18 @@ Each creator of new yTokens for a series has an associated "Repo" that records t Any user may create yTokens of a particular series provided she deposits the appropriate amount of collateral. 1. Deposit ETH into the Treasurer - The user may deposit ETH by paying a desired amount of ETH when calling the `join()` function. + The user may deposit ETH by paying a desired amount of ETH when calling the `topUpCollateral()` function. 2. Make the desired yToken amount - The user may make the desired yToken by calling `make(uint series, uint made, uint paid)` and specifying the series (`series`) desired, the amount of yToken to make (`made`), and the amount of collateral to lock up (`paid`). The amount paid must be greater than the minimum collateral which equals the amount of yTokens made multiplied by the Collateralization Ratio. - + The user may issueYToken the desired yToken by calling `issueYToken(uint series, uint made, uint paid)` and specifying the series (`series`) desired, the amount of yToken to issueYToken (`made`), and the amount of collateral to lock up (`paid`). The amount paid must be greater than the minimum collateral which equals the amount of yTokens made multiplied by the Collateralization Ratio. ### Redeeming a yToken The holder of a Repo may wipe yToken debt in her repo by sending yToken back to the Treasurer. This is accomplished by calling `wipe(uint series, uint credit, uint released)` and specifying the series of the yToken, the amount of yToken debt to wipe (`credit`), and the amount of Ether collateral to be released (`released`). The caller must have sufficient yTokens to satisfy the credit or else the call will fail. Also, the call will fail if the user attempts to release more Ether collateral than the minimum collateral required for the remaining yToken debt. - ### Settlement -After the maturity date for a series is reached, the yTokens for that series may be settled. Settlement is achieved by fixing a Dai price in Ether that will be used to determine how much Ether collateral each yToken holder is permitted to withdraw as payment for her matured yToken. To initiate settlement after the maturity date, any user may call `settlement(uint series)` and specify the series (`series`) to be settled. After the settlement function is called, users may retrieve their funds. A user who holds yTokens to maturity may call `withdraw(uint series, uint256 amount)` specifying the series of the yToken, and the amount of yToken to settle and retrieve the associated Ether. Likewise, a repo holder may close her repo and retrieve the associated Ether by calling `close(uint series)` specifying the series of the yToken. +After the maturity date for a series is reached, the yTokens for that series may be settled. Settlement is achieved by fixing a Dai price in Ether that will be used to determine how much Ether collateral each yToken holder is permitted to withdraw as payment for her matured yToken. To initiate settlement after the maturity date, any user may call `settlement(uint series)` and specify the series (`series`) to be settled. After the settlement function is called, users may retrieve their funds. A user who holds yTokens to maturity may call `withdraw(uint series, uint256 amount)` specifying the series of the yToken, and the amount of yToken to settle and retrieve the associated Ether. Likewise, a repo holder may close her repo and retrieve the associated Ether by calling `close(uint series)` specifying the series of the yToken. ### Liquidation -In order to maintain sufficient collateralization for a repo, when a repo becomes close to becoming undercollateralized, any holder of yTokens of the appropriate series may tender the yTokens and liquidate some or all of the nearly-undercollateralized repo. A repo becomes available for liquidation when the amount of collateral drops below a minimum collateralization ratio. A holder of yToken may liquidate some or all of a repo by calling `liquidate(uint series, address bum, uint256 amount)` specifying a series of the yTokens to be liquidated, the address of the holder of the repo to be liquidated (the `bum`), and the amount of yTokens to contribute to the liquidation. +In order to maintain sufficient collateralization for a repo, when a repo becomes close to becoming undercollateralized, any holder of yTokens of the appropriate series may tender the yTokens and liquidate some or all of the nearly-undercollateralized repo. A repo becomes available for liquidation when the amount of collateral drops below a minimum collateralization ratio. A holder of yToken may liquidate some or all of a repo by calling `liquidate(uint series, address bum, uint256 amount)` specifying a series of the yTokens to be liquidated, the address of the holder of the repo to be liquidated (the `bum`), and the amount of yTokens to contribute to the liquidation. diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index ceec95a..71e6073 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -52,7 +52,10 @@ contract Treasurer is Ownable { } // issue new yToken - function issue(uint256 maturityTime) external returns (uint256 series) { + function createNewYToken(uint256 maturityTime) + external + returns (uint256 series) + { require(maturityTime > now, "treasurer-issue-maturity-is-in-past"); series = totalSeries; require( @@ -66,10 +69,10 @@ contract Treasurer is Ownable { } // add collateral to repo - function join() external payable { + function topUpCollateral() external payable { require( msg.value >= 0, - "treasurer-join-collateralRatio-include-deposit" + "treasurer-topUpCollateral-collateralRatio-include-deposit" ); unlocked[msg.sender] = unlocked[msg.sender].add(msg.value); } @@ -77,22 +80,25 @@ contract Treasurer is Ownable { // remove collateral from repo // amount - amount of ETH to remove from unlocked account // TO-DO: Update as described in https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ - function exit(uint256 amount) external { - require(amount >= 0, "treasurer-exit-insufficient-balance"); + function withdrawCollateral(uint256 amount) external { + require( + amount >= 0, + "treasurer-withdrawCollateral-insufficient-balance" + ); unlocked[msg.sender] = unlocked[msg.sender].sub(amount); msg.sender.transfer(amount); } - // make a new yToken + // issueYToken a new yToken // series - yToken to mint // made - amount of yToken to mint // paid - amount of collateral to lock up - function make(uint256 series, uint256 made, uint256 paid) external { + function issueYToken(uint256 series, uint256 made, uint256 paid) external { require(series < totalSeries, "treasurer-make-unissued-series"); // first check if sufficient capital to lock up require( unlocked[msg.sender] >= paid, - "treasurer-make-insufficient-unlocked-to-lock" + "treasurer-issueYToken-insufficient-unlocked-to-lock" ); Repo memory repo = repos[series][msg.sender]; @@ -100,7 +106,7 @@ contract Treasurer is Ownable { uint256 min = made.wmul(collateralRatio).wmul(rate); require( paid >= min, - "treasurer-make-insufficient-collateral-for-those-tokens" + "treasurer-issueYToken-insufficient-collateral-for-those-tokens" ); // lock msg.sender Collateral, add debtAmount @@ -113,7 +119,7 @@ contract Treasurer is Ownable { // first, ensure yToken is initialized and matures in the future require( yTokens[series].maturityTime() > now, - "treasurer-make-invalid-or-matured-ytoken" + "treasurer-issueYToken-invalid-or-matured-ytoken" ); yTokens[series].mint(msg.sender, made); } diff --git a/migrations/4_deploy_uniswap_mocks.js b/migrations/4_deploy_uniswap_mocks.js index 74dbb13..f06d6e1 100644 --- a/migrations/4_deploy_uniswap_mocks.js +++ b/migrations/4_deploy_uniswap_mocks.js @@ -10,7 +10,7 @@ setup = async web3 => { await oracle.set(rate); await treasurer.setOracle(oracle.address); var maturityDate = (await timestamp("latest", web3)) + 24 * 60 * 60 * 30; - await treasurer.issue(maturityDate.toString()); + await treasurer.createNewYToken(maturityDate.toString()); }; module.exports = function(deployer, network, accounts) { diff --git a/test/treasurer.js b/test/treasurer.js index 42449ea..58412ce 100644 --- a/test/treasurer.js +++ b/test/treasurer.js @@ -26,18 +26,18 @@ contract("Treasurer", async accounts => { var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; currentTimeStamp = currentTimeStamp - 1; await truffleAssert.fails( - TreasurerInstance.issue(currentTimeStamp), + TreasurerInstance.createNewYToken(currentTimeStamp), truffleAssert.REVERT ); - //let series = await TreasurerInstance.issue(currentTimeStamp); + //let series = await TreasurerInstance.createNewYToken(currentTimeStamp); }); it("should issue a new yToken", async () => { var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; var era = currentTimeStamp + SECONDS_IN_DAY; - let series = await TreasurerInstance.issue.call(era.toString()); - await TreasurerInstance.issue(era.toString()); + let series = await TreasurerInstance.createNewYToken.call(era.toString()); + await TreasurerInstance.createNewYToken(era.toString()); let address = await TreasurerInstance.yTokens(series); var yTokenInstance = await YToken.at(address); assert.equal( @@ -48,7 +48,7 @@ contract("Treasurer", async accounts => { }); it("should accept collateral", async () => { - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[1], value: web3.utils.toWei("1") }); @@ -61,12 +61,14 @@ contract("Treasurer", async accounts => { }); it("should return collateral", async () => { - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[1], value: web3.utils.toWei("1") }); var balance_before = await web3.eth.getBalance(accounts[1]); - await TreasurerInstance.exit(web3.utils.toWei("1"), {from: accounts[1]}); + await TreasurerInstance.withdrawCollateral(web3.utils.toWei("1"), { + from: accounts[1] + }); var balance_after = await web3.eth.getBalance(accounts[1]); assert(balance_after > balance_before); }); @@ -76,15 +78,15 @@ contract("Treasurer", async accounts => { assert.equal(_address, OracleMock.address); }); - it("should make new yTokens", async () => { + it("should issueYToken new yTokens", async () => { // create another yToken series with a 24 hour period until maturity var number = await web3.eth.getBlockNumber(); var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; var series = 0; var era = currentTimeStamp + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); //funding - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[1], value: web3.utils.toWei("1") }); @@ -93,8 +95,8 @@ contract("Treasurer", async accounts => { var rate = web3.utils.toWei(".01"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE - // make new yTokens - await TreasurerInstance.make( + // issueYToken new yTokens + await TreasurerInstance.issueYToken( series, web3.utils.toWei("1"), web3.utils.toWei("1"), @@ -108,7 +110,7 @@ contract("Treasurer", async accounts => { assert.equal( balance.toString(), web3.utils.toWei("1"), - "Did not make new yTokens" + "Did not issueYToken new yTokens" ); //check unlocked collateral, lockedCollateralAmount collateral @@ -130,10 +132,10 @@ contract("Treasurer", async accounts => { var currentTimeStamp = await timestamp("latest", web3); var series = 0; var era = currentTimeStamp + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); //funding - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[1], value: web3.utils.toWei("1") }); @@ -143,8 +145,8 @@ contract("Treasurer", async accounts => { var rate = web3.utils.toWei(".01"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE - // make new yTokens - await TreasurerInstance.make( + // issueYToken new yTokens + await TreasurerInstance.issueYToken( series, web3.utils.toWei("1"), web3.utils.toWei("1"), @@ -195,7 +197,7 @@ contract("Treasurer", async accounts => { var series = 2; var era = currentTimeStamp + SECONDS_IN_DAY; await truffleAssert.fails( - TreasurerInstance.issue(era), + TreasurerInstance.createNewYToken(era), truffleAssert.REVERT ); }); @@ -209,15 +211,15 @@ contract("Treasurer", async accounts => { var rate = web3.utils.toWei(".01"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE - // make new yTokens with new account + // issueYToken new yTokens with new account // at 100 dai/ETH, and 150% collateral requirement (set at deployment), // should refuse to create 101 yTokens - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[2], value: web3.utils.toWei("1.5") }); await truffleAssert.fails( - TreasurerInstance.make( + TreasurerInstance.issueYToken( series, web3.utils.toWei("101"), web3.utils.toWei("1.5"), @@ -230,7 +232,7 @@ contract("Treasurer", async accounts => { it("should accept liquidations undercollateralized repos", async () => { var series = 0; var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); // set up oracle const oracle = await Oracle.new(); @@ -238,12 +240,12 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[2], value: web3.utils.toWei("1.5") }); - // make new yTokens with new account - await TreasurerInstance.make( + // issueYToken new yTokens with new account + await TreasurerInstance.issueYToken( series, web3.utils.toWei("100"), web3.utils.toWei("1.5"), @@ -257,7 +259,7 @@ contract("Treasurer", async accounts => { from: accounts[2] }); - //change rate to make tokens undercollateralized + //change rate to issueYToken tokens undercollateralized rate = web3.utils.toWei(".02"); // rate = Dai/ETH await OracleMock.givenAnyReturnUint(rate); await truffleAssert.fails( @@ -314,7 +316,7 @@ contract("Treasurer", async accounts => { it("should allow for settlement", async () => { var series = 0; var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); // set up oracle const oracle = await Oracle.new(); @@ -322,12 +324,12 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[2], value: web3.utils.toWei("1.5") }); - // make new yTokens with new account - await TreasurerInstance.make( + // issueYToken new yTokens with new account + await TreasurerInstance.issueYToken( series, web3.utils.toWei("100"), web3.utils.toWei("1.5"), @@ -343,7 +345,7 @@ contract("Treasurer", async accounts => { it("should allow token holder to withdraw face value", async () => { var series = 0; var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); // set up oracle const oracle = await Oracle.new(); @@ -351,12 +353,12 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[2], value: web3.utils.toWei("1.5") }); - // make new yTokens with new account - await TreasurerInstance.make( + // issueYToken new yTokens with new account + await TreasurerInstance.issueYToken( series, web3.utils.toWei("100"), web3.utils.toWei("1.5"), @@ -391,7 +393,7 @@ contract("Treasurer", async accounts => { it("should allow repo holder to close repo and recieve remaining collateral", async () => { var series = 0; var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; - await TreasurerInstance.issue(era); + await TreasurerInstance.createNewYToken(era); // set up oracle const oracle = await Oracle.new(); @@ -399,12 +401,12 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.join({ + await TreasurerInstance.topUpCollateral({ from: accounts[2], value: web3.utils.toWei("1.5") }); - // make new yTokens with new account - await TreasurerInstance.make( + // issueYToken new yTokens with new account + await TreasurerInstance.issueYToken( series, web3.utils.toWei("100"), web3.utils.toWei("1.5"), From f1cc23431d94d358716ad40af0c9ea2a6f0fcf55 Mon Sep 17 00:00:00 2001 From: josojo Date: Sat, 23 Nov 2019 16:02:21 +0100 Subject: [PATCH 10/10] introducing the collateralToken as erc20 --- contracts/Treasurer.sol | 31 ++++---- migrations/2_deploy.js | 18 +++-- test/treasurer.js | 152 ++++++++++++++++------------------------ 3 files changed, 94 insertions(+), 107 deletions(-) diff --git a/contracts/Treasurer.sol b/contracts/Treasurer.sol index 71e6073..6ad45a3 100644 --- a/contracts/Treasurer.sol +++ b/contracts/Treasurer.sol @@ -2,6 +2,7 @@ pragma solidity ^0.5.2; import "./yToken.sol"; import "./oracle/Oracle.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./libraries/ExponentialOperations.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; @@ -24,11 +25,13 @@ contract Treasurer is Ownable { uint256 public collateralRatio; // collateralization ratio uint256 public minCollateralRatio; // minimum collateralization ratio uint256 public totalSeries = 0; - - constructor(uint256 collateralRatio_, uint256 minCollateralRatio_) - public - Ownable() - { + ERC20 public collateralToken; + constructor( + ERC20 _collateralToken, + uint256 collateralRatio_, + uint256 minCollateralRatio_ + ) public Ownable() { + collateralToken = _collateralToken; collateralRatio = collateralRatio_; minCollateralRatio = minCollateralRatio_; } @@ -69,12 +72,16 @@ contract Treasurer is Ownable { } // add collateral to repo - function topUpCollateral() external payable { + function topUpCollateral(uint256 amountCollateral) external payable { require( - msg.value >= 0, + collateralToken.transferFrom( + msg.sender, + address(this), + amountCollateral + ), "treasurer-topUpCollateral-collateralRatio-include-deposit" ); - unlocked[msg.sender] = unlocked[msg.sender].add(msg.value); + unlocked[msg.sender] = unlocked[msg.sender].add(amountCollateral); } // remove collateral from repo @@ -86,7 +93,7 @@ contract Treasurer is Ownable { "treasurer-withdrawCollateral-insufficient-balance" ); unlocked[msg.sender] = unlocked[msg.sender].sub(amount); - msg.sender.transfer(amount); + collateralToken.transfer(msg.sender, amount); } // issueYToken a new yToken @@ -225,7 +232,7 @@ contract Treasurer is Ownable { repo.debtAmount = repo.debtAmount.sub(amount); repos[series][bum] = repo; // send bitten funds - msg.sender.transfer(bitten); + collateralToken.transfer(msg.sender, bitten); } // trigger settlement @@ -261,7 +268,7 @@ contract Treasurer is Ownable { uint256 rate = settled[series]; uint256 goods = amount.wmul(rate); - msg.sender.transfer(goods); + collateralToken.transfer(msg.sender, goods); } // series - matured yToken @@ -292,6 +299,6 @@ contract Treasurer is Ownable { repo.debtAmount = 0; repos[series][msg.sender] = repo; - msg.sender.transfer(goods); + collateralToken.transfer(msg.sender, goods); } } diff --git a/migrations/2_deploy.js b/migrations/2_deploy.js index f2f0e03..e0a466e 100644 --- a/migrations/2_deploy.js +++ b/migrations/2_deploy.js @@ -1,10 +1,18 @@ const Treasurer = artifacts.require("Treasurer"); const Token = artifacts.require("yToken"); const MockContract = artifacts.require("./MockContract"); +const ERC20Mintable = artifacts.require("./ERC20Mintable"); -module.exports = function(deployer, network, accounts) { - //if (network == "") - //Token stands in for Dai - deployer.deploy(MockContract); - deployer.deploy(Treasurer, web3.utils.toWei("1.5"), web3.utils.toWei("1.05")); +module.exports = async function(deployer, network, accounts) { + if (network == "development") { + //Token stands in for Dai + await deployer.deploy(ERC20Mintable); + collateralToken = await ERC20Mintable.deployed(); + await deployer.deploy( + Treasurer, + collateralToken.address, + web3.utils.toWei("1.5"), + web3.utils.toWei("1.05") + ); + } }; diff --git a/test/treasurer.js b/test/treasurer.js index 58412ce..8e715a1 100644 --- a/test/treasurer.js +++ b/test/treasurer.js @@ -2,6 +2,8 @@ const Treasurer = artifacts.require("./Treasurer"); const YToken = artifacts.require("./yToken"); const MockContract = artifacts.require("./MockContract"); const Oracle = artifacts.require("./Oracle"); +const ERC20 = artifacts.require("ERC20"); + const truffleAssert = require("truffle-assertions"); const helper = require("ganache-time-traveler"); const {timestamp} = require("./../src/utilities"); @@ -12,8 +14,14 @@ contract("Treasurer", async accounts => { const collateralRatio = web3.utils.toWei("1.5"); const minCollateralRatio = web3.utils.toWei("1.05"); let TreasurerInstance; + let collateralToken; + let erc20; beforeEach("deploy OracleMock", async () => { + erc20 = await ERC20.new(); + collateralToken = await MockContract.new(); + await collateralToken.givenAnyReturnBool(true); TreasurerInstance = await Treasurer.new( + collateralToken.address, collateralRatio, minCollateralRatio ); @@ -48,9 +56,8 @@ contract("Treasurer", async accounts => { }); it("should accept collateral", async () => { - await TreasurerInstance.topUpCollateral({ - from: accounts[1], - value: web3.utils.toWei("1") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1"), { + from: accounts[1] }); var result = await TreasurerInstance.unlocked(accounts[1]); assert.equal( @@ -61,16 +68,21 @@ contract("Treasurer", async accounts => { }); it("should return collateral", async () => { - await TreasurerInstance.topUpCollateral({ - from: accounts[1], - value: web3.utils.toWei("1") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1"), { + from: accounts[1] }); - var balance_before = await web3.eth.getBalance(accounts[1]); await TreasurerInstance.withdrawCollateral(web3.utils.toWei("1"), { from: accounts[1] }); - var balance_after = await web3.eth.getBalance(accounts[1]); - assert(balance_after > balance_before); + const transferFunctionality = erc20.contract.methods + .transfer(accounts[1], web3.utils.toWei("1")) + .encodeABI(); + assert.equal( + 1, + await collateralToken.invocationCountForCalldata.call( + transferFunctionality + ) + ); }); it("should provide Oracle address", async () => { @@ -86,9 +98,8 @@ contract("Treasurer", async accounts => { var era = currentTimeStamp + SECONDS_IN_DAY; await TreasurerInstance.createNewYToken(era); //funding - await TreasurerInstance.topUpCollateral({ - from: accounts[1], - value: web3.utils.toWei("1") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1"), { + from: accounts[1] }); // set up oracle const oracle = await Oracle.new(); @@ -135,9 +146,8 @@ contract("Treasurer", async accounts => { await TreasurerInstance.createNewYToken(era); //funding - await TreasurerInstance.topUpCollateral({ - from: accounts[1], - value: web3.utils.toWei("1") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1"), { + from: accounts[1] }); // set up oracle @@ -188,21 +198,6 @@ contract("Treasurer", async accounts => { ); }); - /******** No longer relevant, but saved as an example - it("should not permit re-issuing a series", async() => { - const TreasurerInstance = await Treasurer.deployed(); - var number = await web3.eth.getBlockNumber(); - var currentTimeStamp = (await web3.eth.getBlock(number)).timestamp; - // reuse same series number - var series = 2; - var era = currentTimeStamp + SECONDS_IN_DAY; - await truffleAssert.fails( - TreasurerInstance.createNewYToken(era), - truffleAssert.REVERT - ); - }); - *****/ - it("should refuse to create an undercollateralized repos", async () => { var series = 0; @@ -214,9 +209,8 @@ contract("Treasurer", async accounts => { // issueYToken new yTokens with new account // at 100 dai/ETH, and 150% collateral requirement (set at deployment), // should refuse to create 101 yTokens - await TreasurerInstance.topUpCollateral({ - from: accounts[2], - value: web3.utils.toWei("1.5") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1.5"), { + from: accounts[2] }); await truffleAssert.fails( TreasurerInstance.issueYToken( @@ -240,9 +234,8 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.topUpCollateral({ - from: accounts[2], - value: web3.utils.toWei("1.5") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1.5"), { + from: accounts[2] }); // issueYToken new yTokens with new account await TreasurerInstance.issueYToken( @@ -272,7 +265,6 @@ contract("Treasurer", async accounts => { truffleAssert.REVERT, "treasurer-wipe-insufficient-token-balance" ); - var balance_before = await web3.eth.getBalance(accounts[3]); // attempt to liquidate const result = await TreasurerInstance.liquidate( @@ -283,20 +275,14 @@ contract("Treasurer", async accounts => { ); //check received 1.05 - const tx = await web3.eth.getTransaction(result.tx); - var balance_after = await web3.eth.getBalance(accounts[3]); - const total = - Number(balance_after) - - Number(balance_before) + - result.receipt.gasUsed * tx.gasPrice; - //try to constrain the test rather than use an inequality (I think the Javascript math is losing precision) - assert( - total > Number(web3.utils.toWei("1.04999")), - "liquidation funds not received" - ); - assert( - total < Number(web3.utils.toWei("1.05001")), - "liquidation funds not received" + const transferFunctionality = erc20.contract.methods + .transfer(accounts[3], web3.utils.toWei("1.05")) + .encodeABI(); + assert.equal( + 1, + await collateralToken.invocationCountForCalldata.call( + transferFunctionality + ) ); //check unlocked collateral, lockedCollateralAmount collateral @@ -324,9 +310,8 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.topUpCollateral({ - from: accounts[2], - value: web3.utils.toWei("1.5") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1.5"), { + from: accounts[2] }); // issueYToken new yTokens with new account await TreasurerInstance.issueYToken( @@ -353,9 +338,8 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.topUpCollateral({ - from: accounts[2], - value: web3.utils.toWei("1.5") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1.5"), { + from: accounts[2] }); // issueYToken new yTokens with new account await TreasurerInstance.issueYToken( @@ -374,23 +358,18 @@ contract("Treasurer", async accounts => { {from: accounts[2]} ); - var balance_after = await web3.eth.getBalance(accounts[2]); - const tx = await web3.eth.getTransaction(result.tx); - const total = - Number(balance_after) - - Number(balance_before) + - result.receipt.gasUsed * tx.gasPrice; - assert( - total > Number(web3.utils.toWei(".24999")), - "withdrawn funds not received" - ); - assert( - total < Number(web3.utils.toWei(".250001")), - "withdrawn funds not received" + const transferFunctionality = erc20.contract.methods + .transfer(accounts[2], web3.utils.toWei("0.25")) + .encodeABI(); + assert.equal( + 1, + await collateralToken.invocationCountForCalldata.call( + transferFunctionality + ) ); }); - it("should allow repo holder to close repo and recieve remaining collateral", async () => { + it("should allow repo holder to close repo and receive remaining collateral", async () => { var series = 0; var era = (await timestamp("latest", web3)) + SECONDS_IN_DAY; await TreasurerInstance.createNewYToken(era); @@ -401,9 +380,8 @@ contract("Treasurer", async accounts => { await OracleMock.givenAnyReturnUint(rate); // should price ETH at $100 * ONE //fund account - await TreasurerInstance.topUpCollateral({ - from: accounts[2], - value: web3.utils.toWei("1.5") + await TreasurerInstance.topUpCollateral(web3.utils.toWei("1.5"), { + from: accounts[2] }); // issueYToken new yTokens with new account await TreasurerInstance.issueYToken( @@ -417,22 +395,16 @@ contract("Treasurer", async accounts => { var balance_before = await web3.eth.getBalance(accounts[2]); //run close - const result = await TreasurerInstance.close(series, {from: accounts[2]}); - - var balance_after = await web3.eth.getBalance(accounts[2]); - const tx = await web3.eth.getTransaction(result.tx); - var balance_after = await web3.eth.getBalance(accounts[2]); - const total = - Number(balance_after) - - Number(balance_before) + - result.receipt.gasUsed * tx.gasPrice; - assert( - total > Number(web3.utils.toWei(".4999")), - "repo funds not received" - ); - assert( - total < Number(web3.utils.toWei(".5001")), - "repo funds not received" + await TreasurerInstance.close(series, {from: accounts[2]}); + + const transferFunctionality = erc20.contract.methods + .transfer(accounts[2], web3.utils.toWei("0.5")) + .encodeABI(); + assert.equal( + 1, + await collateralToken.invocationCountForCalldata.call( + transferFunctionality + ) ); }); });