diff --git a/.gitignore b/.gitignore index 3cae04f1..f07f8d5c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ node_modules .env db .vscode +abis +verify.js.map +verify.js +flattened.*.sol diff --git a/Verify.md b/Verify.md new file mode 100644 index 00000000..f8123605 --- /dev/null +++ b/Verify.md @@ -0,0 +1,89 @@ +# Verify Contracts + +For each contract whose address appears in migration.json (and therefore is a "migrated contract") we send the contract's solidity code to etherscan.io which will attempt to "verify" that the given code corresponds to the bytecodes deployed at the address given in migration.json. + +**Note** Contract validation via this script currently does not work on Windows (truffle-flattener generates invalid flattened .sol files). The fix for that is at this writing in PR at truffle-flattener. + +## Setup +1. In the project root, create an ".env" file (or use the existing one) that contains: +``` +APIKEY=[API key from https://etherscan.io/myapikey] +``` + +Alternately you can supply this as an OS environment variable when you run `build.verify`. + +2. initialize just one time, required by `build.verify`: + +```script +npm run verify.initialize +``` + +3. build just one time or whenever you modify verify.ts, required by `verify`: + +```script +npm run verify.build +``` + +## Verify + +### Verify all of the contracts migrated to the given network + +```script +npm run verify -- -p [provider url] -n kovan +``` + +### Verify all of the contracts of a specific Arc version migrated to the given network + +```script +npm run verify -- -p [provider url] -n kovan -v 0.0.1-rc.18 +``` + +The default Arc version is the last version listed in the migration.json file for the given network. + +### Verify a single scheme + +```script +npm run verify -- -c UpgradeScheme -p [provider url] -n kovan +``` + +Outputs a GUID that you can use with `npm run verify -- -g`. + +### Verify a single scheme at an address + +```script +npm run verify -- -c UpgradeScheme -a 0x12345... -p [provider url] -n kovan +``` + +### Obtain a flattened contract + +Output the flattened script to a file named "flattened.[contractName].sol", by supplying the absolute path to a folder in which to write the file(s): + +```script +npm run verify -- -f [absolute folder path] [...] -p [provider url] -n kovan +``` + +### Check verification status, given GUID + +Given the GUID that is output by `npm run verify`: + +```script +npm run verify -- -g [GUID] -n kovan +``` + +## Help +```script +npm run verify.help +``` + +## Lint + +```script +npm run verify.lint +``` + +And fix: + +```script +npm run verify.lint.andFix +``` + diff --git a/package-lock.json b/package-lock.json index 57d7eca1..1b637cdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,10 +57,52 @@ "openzeppelin-solidity": "2.1.3" } }, + "@resolver-engine/core": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.2.1.tgz", + "integrity": "sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "request": "^2.85.0" + } + }, + "@resolver-engine/fs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.2.1.tgz", + "integrity": "sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg==", + "dev": true, + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0" + } + }, + "@resolver-engine/imports": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.2.2.tgz", + "integrity": "sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg==", + "dev": true, + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0" + } + }, + "@resolver-engine/imports-fs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz", + "integrity": "sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ==", + "dev": true, + "requires": { + "@resolver-engine/fs": "^0.2.1", + "@resolver-engine/imports": "^0.2.2", + "debug": "^3.1.0" + } + }, "@types/node": { - "version": "10.14.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.7.tgz", - "integrity": "sha512-on4MmIDgHXiuJDELPk1NFaKVUxxCFr37tm8E9yN6rAiF5Pzp/9bBfBHkoexqRiY+hk/Z04EJU9kKEb59YqJ82A==" + "version": "10.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.10.tgz", + "integrity": "sha512-V8wj+w2YMNvGuhgl/MA5fmTxgjmVHVoasfIaxMMZJV6Y8Kk+Ydpi1z2whoShDCJ2BuNVoqH/h1hrygnBxkrw/Q==" }, "accepts": { "version": "1.3.7", @@ -189,7 +231,7 @@ }, "ansi-colors": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", "integrity": "sha1-csMd4qDZoszQysMMyYI+6y9kNLU=", "requires": { "ansi-bgblack": "^0.1.1", @@ -401,6 +443,12 @@ } } }, + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -465,6 +513,24 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -537,9 +603,9 @@ } }, "bluebird": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", - "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==" + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" }, "bn.js": { "version": "4.11.8", @@ -594,7 +660,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "requires": { "buffer-xor": "^1.0.3", @@ -719,6 +785,12 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -906,6 +978,47 @@ "delayed-stream": "~1.0.0" } }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "command-line-usage": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-5.0.5.tgz", + "integrity": "sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "chalk": "^2.4.1", + "table-layout": "^0.4.3", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + } + } + }, "commander": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", @@ -988,7 +1101,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", @@ -1000,7 +1113,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", @@ -1156,6 +1269,12 @@ } } }, + "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", @@ -1210,6 +1329,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", @@ -1234,6 +1359,12 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" }, + "dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "dev": true + }, "drbg.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", @@ -1333,6 +1464,12 @@ "is-symbol": "^1.0.2" } }, + "es6-promisify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.1.tgz", + "integrity": "sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1478,9 +1615,9 @@ } }, "eslint-plugin-import": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz", - "integrity": "sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.0.tgz", + "integrity": "sha512-PZpAEC4gj/6DEMMoU2Df01C5c50r7zdGIN52Yfi7CvvWaYssG7Jt5R9nFG5gmqodxNOz9vQS87xk6Izdtpdrig==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -1493,7 +1630,7 @@ "lodash": "^4.17.11", "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.10.0" + "resolve": "^1.11.0" }, "dependencies": { "debug": { @@ -1507,7 +1644,7 @@ }, "doctrine": { "version": "1.5.0", - "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { @@ -1538,9 +1675,9 @@ }, "dependencies": { "ignore": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.1.tgz", - "integrity": "sha512-DWjnQIFLenVrwyRCKZT+7a7/U4Cqgar4WG8V++K3hw+lrW1hc/SIwdiGmtxKCVACmHULTuGeBbHJmbwW7/sAvA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.2.tgz", + "integrity": "sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ==", "dev": true } } @@ -1823,9 +1960,9 @@ } }, "express": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.0.tgz", - "integrity": "sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -1982,6 +2119,15 @@ } } }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -2007,6 +2153,32 @@ "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2114,9 +2286,9 @@ "dev": true }, "ganache-cli": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.4.3.tgz", - "integrity": "sha512-3G+CK4ojipDvxQHlpX8PjqaOMRWVcaLZZSW97Bv7fdcPTXQwkji2yY5CY6J12Atiub4M4aJc0va+q3HXeerbIA==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.4.4.tgz", + "integrity": "sha512-JWygbyZuM2GQl2ZvU7tBkjpgJaKE/XEtB99ech17XTouuqLU5rBcyO3sMb/L83wAtzr0gBnTgenIBl+OeREpJw==", "requires": { "bn.js": "4.11.8", "source-map-support": "0.5.9", @@ -2634,6 +2806,13 @@ "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } } }, "http-https": { @@ -2716,14 +2895,14 @@ "integrity": "sha1-J4QdcoZ920JCzWEtecEGM4gcang=" }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", - "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.4.1.tgz", + "integrity": "sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw==", "requires": { "ansi-escapes": "^3.2.0", "chalk": "^2.4.2", @@ -3063,7 +3242,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -3087,6 +3266,18 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, "log-ok": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/log-ok/-/log-ok-0.1.1.tgz", @@ -3106,7 +3297,7 @@ }, "log-utils": { "version": "0.2.1", - "resolved": "http://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz", + "resolved": "https://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz", "integrity": "sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8=", "requires": { "ansi-colors": "^0.2.0", @@ -3261,7 +3452,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { @@ -3299,7 +3490,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -3314,9 +3505,9 @@ } }, "mock-fs": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.9.0.tgz", - "integrity": "sha512-aUj0qIniTNxzGqAC61Bvro7YD37tIBnMw3wpClucUVgNBS7r6YQn/M4wuoH7SGteKz4SvC1OBeDsfpG0MYC+1Q==" + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.10.1.tgz", + "integrity": "sha512-w22rOL5ZYu6HbUehB5deurghGM0hS/xBVyHMGKOuQctkk93J9z9VEOhDsiWrXOprVNQpP9uzGKdl8v9mFspKuw==" }, "moment": { "version": "2.24.0", @@ -3329,13 +3520,13 @@ "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=" }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mute-stream": { "version": "0.0.7", - "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "mz": { @@ -3445,7 +3636,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -3453,7 +3644,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -3567,7 +3758,7 @@ }, "os-tmpdir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-cancelable": { @@ -3671,7 +3862,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { @@ -3729,7 +3920,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { @@ -3821,9 +4012,9 @@ "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "version": "2.0.1", + "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", @@ -3967,9 +4158,9 @@ } }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.33.tgz", + "integrity": "sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw==" }, "public-encrypt": { "version": "4.0.3", @@ -4013,6 +4204,12 @@ "strict-uri-encode": "^1.0.0" } }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, "radio-symbol": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/radio-symbol/-/radio-symbol-2.0.0.tgz", @@ -4193,6 +4390,12 @@ } } }, + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -4244,9 +4447,9 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -4350,9 +4553,9 @@ } }, "secp256k1": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.0.tgz", - "integrity": "sha512-YlUIghD6ilkMkzmFJpIdVjiamv2S8lNZ9YMwm1XII9JC0NcR5qQiv2DOp/G37sExBtaMStzba4VDJtvBXEbmMQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", "requires": { "bindings": "^1.5.0", "bip66": "^1.1.5", @@ -4360,7 +4563,7 @@ "create-hash": "^1.2.0", "drbg.js": "^1.0.1", "elliptic": "^6.4.1", - "nan": "^2.13.2", + "nan": "^2.14.0", "safe-buffer": "^5.1.2" } }, @@ -4411,6 +4614,11 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" } } }, @@ -4451,9 +4659,9 @@ } }, "set-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-3.0.0.tgz", - "integrity": "sha512-tqkg9wJ2TOsxbzIMG5NMAmzjdbDTAD0in7XuUzmFpJE4Ipi2QFBfgC2Z1/gfxcAmWCPsuutiEJyDIMRsrjrMOQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-3.0.1.tgz", + "integrity": "sha512-w6n3GUPYAWQj4ZyHWzD7K2FnFXHx9OTwJYbWg+6nXjG8sCLfs9DGv+KlqglKIIJx+ks7MlFuwFW2RBPb+8V+xg==", "requires": { "is-plain-object": "^2.0.4" } @@ -4470,7 +4678,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", @@ -4553,6 +4761,12 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "solidity-parser-antlr": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.5.tgz", + "integrity": "sha512-5GzhIs4hpY3XnGwMndgrOksD567O5WdUQPbpy2n2WA1m3algzUKYMf+Ne/QHd36TTUNvVV+iTWD5tKaCZfaOjg==", + "dev": true + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", @@ -4587,7 +4801,7 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, @@ -4626,7 +4840,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -4644,7 +4858,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -4760,7 +4974,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-hex-prefix": { @@ -4811,9 +5025,9 @@ } }, "table": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/table/-/table-5.3.3.tgz", - "integrity": "sha512-3wUNCgdWX6PNpOe3amTTPWPuF6VGvgzjKCaO1snFj0z7Y3mUPWf5+zDtxUVGispJkDECPmR29wbzh6bVMOHbcw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.1.tgz", + "integrity": "sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==", "dev": true, "requires": { "ajv": "^6.9.1", @@ -4835,18 +5049,48 @@ } } }, + "table-layout": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.4.tgz", + "integrity": "sha512-uNaR3SRMJwfdp9OUr36eyEi6LLsbcTqTO/hfTsNviKsNeyMBPICJCC7QXRF3+07bAP6FRwA8rczJPBqXDc0CkQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + } + } + }, "tar": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", + "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", + "minipass": "^2.3.5", + "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "yallist": "^3.0.3" } }, "tar-stream": { @@ -4941,7 +5185,7 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "time-stamp": { @@ -5004,10 +5248,112 @@ } } }, + "truffle-flattener": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.4.0.tgz", + "integrity": "sha512-hKpsuDBZEhH2TOTBDfKtFXJhvPbhOot/ZneKZoD7tFJ14PU2tz4C87GrenSt+TZF+iNlAjA9hq42ofl/Ynrn6w==", + "dev": true, + "requires": { + "@resolver-engine/imports-fs": "^0.2.2", + "find-up": "^2.1.0", + "mkdirp": "^0.5.1", + "solidity-parser-antlr": "^0.4.0", + "tsort": "0.0.1" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } + }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + } + } + }, + "tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", + "dev": true + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } }, "tunnel-agent": { "version": "0.6.0", @@ -5048,6 +5394,18 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.2.tgz", + "integrity": "sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -5519,9 +5877,27 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "dependencies": { + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + } + } + }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", @@ -5543,7 +5919,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -5553,7 +5929,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" diff --git a/package.json b/package.json index 1bcb8fca..ecc3756f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,13 @@ "prepare-release": "./prepare-release.sh", "release": "./release.sh", "prune-arc-build": "node ./pruneArcBuild.js", - "postinstall": "npm run prune-arc-build" + "postinstall": "npm run prune-arc-build", + "verify.initialize": "npm explore @daostack/arc -- npm install openzeppelin-solidity @daostack/infra --no-save && npm explore @daostack/infra -- npm install openzeppelin-solidity --no-save && npm explore @daostack/arc-hive -- npm install openzeppelin-solidity --no-save", + "verify.build": "node node_modules/typescript/bin/tsc verify.ts -sourceMap", + "verify.help": "node verify.js -h", + "verify.lint": "tslint -c tslint.json verify.ts", + "verify.lint.andFix": "npm run verify.lint -- --fix", + "verify": "node verify.js" }, "repository": { "type": "git", @@ -54,11 +60,22 @@ "yargs": "^12.0.2" }, "devDependencies": { + "axios": "^0.18.0", + "command-line-args": "^5.0.2", + "command-line-usage": "^5.0.5", + "dotenv": "^7.0.0", + "es6-promisify": "^6.0.1", "eslint": "^5.16.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.16.0", "eslint-plugin-node": "^8.0.1", "eslint-plugin-promise": "^4.0.1", - "eslint-plugin-standard": "^4.0.0" + "eslint-plugin-standard": "^4.0.0", + "ethereumjs-abi": "^0.6.7", + "glob": "^7.1.3", + "querystring": "^0.2.0", + "truffle-flattener": "^1.3.0", + "tslint": "^5.14.0", + "typescript": "^3.3.3333" } } diff --git a/prepare-release.sh b/prepare-release.sh index 2798c2db..3a59d57e 100755 --- a/prepare-release.sh +++ b/prepare-release.sh @@ -3,9 +3,11 @@ set -e source .env - # npm ci echo "Installing NPM modules..." +# best to start from sratch or the "verify" script may fail +rm -r node_modules +rm package-lock.json npm install npm ci # initial Arc vrsion to use @@ -51,4 +53,16 @@ git add -A && git commit -m "release $(cat package.json | jq -r '.version')" echo "Pushing to github..." git push -f # done -echo "Done!" +echo "Pushed!" + +echo "Setting up verifications..." +npm run verify.initialize +npm run verify.build + +echo "Verifying..." +read -n 1 -s -r -p "Press any key to verify contracts on kovan" +npm run verify kovan +read -n 1 -s -r -p "Press any key to verify contracts on rinkeby" +npm run verify rinkeby +read -n 1 -s -r -p "Press any key to verify contracts on main" +npm run verify main diff --git a/pruneArcBuild.js b/pruneArcBuild.js index ad1704a4..42cf7e5f 100644 --- a/pruneArcBuild.js +++ b/pruneArcBuild.js @@ -10,14 +10,14 @@ const spinner = ora() spinner.info(`Starts pruning Arc JSON files`) files.filter(file => { - const { contractName, abi, bytecode, deployedBytecode } = require(`${file}`) + const { contractName, abi, bytecode, deployedBytecode, compiler } = require(`${file}`) spinner.info(`Pruning ${contractName}`) fs.writeFileSync( file, JSON.stringify( - { contractName, abi, bytecode, deployedBytecode }, + { contractName, abi, bytecode, deployedBytecode, compiler }, undefined, 2 ), diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..7e183bb9 --- /dev/null +++ b/tslint.json @@ -0,0 +1,46 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "indent": [ + true, + "spaces", + 2 + ], + "only-arrow-functions": false, + "no-var-requires": false, + "quotemark": [ + true, + "single" + ], + "array-type": [ + true, + "generic" + ], + "variable-name": [ + true, + "ban-keywords", + "check-format", + "allow-leading-underscore" + ], + "max-classes-per-file": false, + "trailing-comma": [ + true, + { + "multiline": { + "objects": "always", + "arrays": "always", + "functions": "never", + "typeLiterals": "ignore" + }, + "singleline": "never", + "esSpecCompliant": true + } + ], + "no-console": false + }, + "rulesDirectory": [] +} diff --git a/verify.ts b/verify.ts new file mode 100644 index 00000000..e0fca7be --- /dev/null +++ b/verify.ts @@ -0,0 +1,283 @@ +const commandLineArgs = require('command-line-args'); +const commandLineUsage = require('command-line-usage'); +const ora = require('ora'); +require('dotenv').config(); +const axios = require('axios'); +const glob = require('glob'); +const path = require('path'); +import * as truffleFlattener from 'truffle-flattener'; +// tslint:disable-next-line: variable-name +const Web3 = require('web3'); +const fs = require('fs'); +const querystring = require('querystring'); +const abi = require('ethereumjs-abi'); +import { promisify } from 'es6-promisify'; + +const sleep = (milliseconds: number): Promise => { + return new Promise((resolve: () => void): any => setTimeout(resolve, milliseconds)); +}; + +// tslint:disable: max-line-length +const optionDefinitions = [ + { name: 'help', alias: 'h', type: Boolean, description: 'show these command line options' }, + { name: 'version', alias: 'v', type: String, description: 'Optional Arc package version number. Default is the last version listed in migration.json.' }, + { name: 'contractAddress', alias: 'a', type: String, description: 'Optional address of a single contract to verify, instead of the default. Must be given with \'contractName\'.' }, + { name: 'contractName', alias: 'c', type: String, description: 'Optional name of a single contract to verify, instead of verifying all of them.' }, + { name: 'network', alias: 'n', type: String, description: 'Required name of the network, such as kovan, rinkeby or mainnet.' }, + { name: 'provider', alias: 'p', type: String, description: 'Required url for web3 network provider (not needed for -g).' }, + { name: 'check', alias: 'g', type: String, description: 'Given verify GUID, check contract verification status. Ignores other options.' }, + { name: 'outputFlattened', alias: 'f', type: String, description: 'When verifying, absolute path where to save the flattened .sol file to flattened.["contractName"].sol.' }, +]; +// tslint:enable: max-line-length + +const options = commandLineArgs(optionDefinitions); + +const usage = (): void => { + const sections = [ + { + content: 'Verify migrated Arc contracts to EtherScan.io', + header: 'Verify Contracts', + }, + { + header: 'Options', + optionList: optionDefinitions, + }, + ]; + + console.log(commandLineUsage(sections)); +}; + +const error = (message: string, showUsage: boolean = false) => { + + console.error(message); + if (showUsage) { + usage(); + } + process.exit(1); +}; + +if (options.help) { + usage(); + process.exit(0); +} + +if (!options.network) { + error(`'network' is required. Run 'npm run help' for cli information.`); +} + +if (options.contractAddress && !options.contractName) { + error(`contractName is required when contractAddress is given. Run 'npm run help' for cli information.`); +} + +const APIKEY = process.env.APIKEY; + +if (!APIKEY) { + error(`APIKEY is not found. See README.md for more information.`); +} + +let addresses = {} as any; +let allAddresses = {} as any; +let web3: any; + +if (!options.check) { + + if (!options.provider) { + error(`'provider' is required. Run 'npm run help' for cli information.`); + } + + /** + * Enumerate contract names (each with its migrated address) and + * fetch the .sol file for it. + */ + const migratedContracts = require('./migration.json'); + + options.version = options.version || + migratedContracts[options.network] && + // tslint:disable-next-line: max-line-length + (Object.keys(migratedContracts[options.network].base)[Object.keys(migratedContracts[options.network].base).length - 1]); + + allAddresses = (migratedContracts[options.network] && + migratedContracts[options.network].base[options.version]) || undefined; + + if (!allAddresses) { + error(`contracts were not deployed to ${options.network}, or invalid network name`); + } + + if (options.contractName && options.contractAddress) { + addresses[options.contractName] = options.contractAddress; + } else { + if (options.contractName) { + if (!allAddresses[options.contractName]) { + error( + `contract ${options.contractName} has not been not deployed to ${options.network}, or invalid contract name`); + } + addresses[options.contractName] = allAddresses[options.contractName]; + } else { + addresses = allAddresses; + } + } + web3 = new Web3(options.provider); +} + +const processContracts = async (): Promise => { + let exitCode = 1; + let anySucceeded = false; + let spinner: any; + + try { + + const etherscanUrl = + `https://api${options.network === 'mainnet' ? '' : ('-' + options.network)}.etherscan.io/api`; + + if (options.check) { + // check is the GUID + const result = await validateResult(options.check, etherscanUrl); + console.log(`Verification status: ${result.result}`); + exitCode = 0; + } else { + + console.log(`Verifying contract(s) on ${options.network}, Arc version ${options.version}...`); + // tslint:disable-next-line: forin + for (const contractName in addresses) { + + let constructorArguments: string; + const address = addresses[contractName]; + + switch (contractName) { + case 'GEN': + case 'ControllerCreator': + // ignore these + continue; + + case 'Redeemer': + constructorArguments = await getConstructorParams(address, 128); + break; + case 'GenesisProtocol': + case 'DaoCreator': + case 'DAORegistry': + constructorArguments = await getConstructorParams(address, 64); + break; + } + + spinner = ora(); + spinner.start(`${contractName} at ${addresses[contractName]}`); + + let foundIn = './node_modules/@daostack/arc'; + process.chdir(path.join(__dirname, foundIn)); + + let solFilePath = glob.sync(`./contracts/**/${contractName}.sol`); + if (!solFilePath.length) { + foundIn = './node_modules/@daostack/infra'; + process.chdir(path.join(__dirname, foundIn)); + solFilePath = glob.sync(`./contracts/**/${contractName}.sol`); + } + + if (!solFilePath.length) { + foundIn = './node_modules/@daostack/arc-hive'; + process.chdir(path.join(__dirname, foundIn)); + solFilePath = glob.sync(`./contracts/**/${contractName}.sol`); + } + + if (!solFilePath.length) { + spinner.fail(`contract ${contractName}.sol not found`); + continue; + } + + const flattened = await truffleFlattener([solFilePath[0]]); + + if (options.outputFlattened) { + fs.writeFileSync(path.join(options.outputFlattened, `flattened.${contractName}.sol`), flattened); + } + + let version = + require(`${foundIn}/build/contracts/${contractName}.json`).compiler.version; + version = `v${version.substr(0, version.indexOf('Emscripten') - 1)}`; + + const apiConfig = { + action: 'verifysourcecode', + apikey: APIKEY, + compilerVersion: version, + constructorArguements: constructorArguments, + // constructorArguements: constructorArguments ? constructorArguments.toString('hex') : '', + contractaddress: addresses[contractName], + contractname: contractName, + module: 'contract', + optimizationUsed: '1', + runs: '200', + sourceCode: flattened, + }; + + const encodedPostData = querystring.stringify(apiConfig).replace(/%20/g, '+'); + const response = await axios.post(etherscanUrl, encodedPostData, + { + headers: { + 'Content-Length': encodedPostData.length, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + } + ); + + const result = response.data; + + if (result.status === '1') { + // 1 = submission success, use the guid returned (result.result) to check the status of the submission. + anySucceeded = true; + const verifyResult = await validateResult(result.result, etherscanUrl); + if (verifyResult.result !== 'Pending in queue') { + spinner.fail( + `${contractName} at ${addresses[contractName]} ${verifyResult.result}, GUID: ${result.result}`); + } else { + spinner.succeed( + `${contractName} at ${addresses[contractName]} ${verifyResult.result}, GUID: ${result.result}`); + } + } else { + if (result.result.indexOf('already verified') !== -1) { + spinner.info(`${contractName} at ${addresses[contractName]} ${result.result}`); + } else { + spinner.fail(`${contractName} at ${addresses[contractName]} ${result.result}`); + } + } + // await sleep(500); + // spinner.succeed(`${ contractName } at ${ addresses[contractName] } `); + } + exitCode = 0; + } + } catch (ex) { + if (spinner) { + spinner.fail(); + } + console.error(ex.message); + } finally { + if (anySucceeded) { + // tslint:disable-next-line: max-line-length + console.log(`In-queue validation(s) may or may succeed. To confirm, use -g option with GUID or check on https://${options.network === 'mainnet' ? '' : (options.network + '.')}etherscan.io/contractsVerified`); + } + } + + process.exit(exitCode); +}; + +/** + * Given a GUID, confirms whether the validation really did succeed + * @param guid + * @param url + */ +const validateResult = async (guid: string, url: string): Promise => { + const response = await axios.get(url, + { + params: + { module: 'contract', action: 'checkverifystatus', guid }, + }); + + return response.data; +}; + +// const contructorParamsPrefix = 'a165627a7a72305820'; + +const getConstructorParams = async (address: string, bytes: number): Promise => { + const code = await promisify((callback: any): any => + web3.eth.getCode(address, callback))() as string; + return code.substr(code.length - bytes); +}; + +processContracts();