diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..94b07f0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + "extends": "eslint-config-google", + "parserOptions": { + "ecmaVersion": 6, + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } + }, + "rules": { + "max-len": "off", + "require-jsdoc": "off", + } +}; diff --git a/README.md b/README.md index b6bfb0e..3ed83b1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,17 @@ This repo contains smart contracts that are under development. Check out the [wiki](https://github.com/transmute-industries/network-contracts/wiki) for more info! +## Install the project + +``` +npm install +``` + +## Run the tests + ``` -npm i -npm run test +npm install -g ganache-cli +ganache-cli +npm run test:unit +npm run test:integration ``` diff --git a/package-lock.json b/package-lock.json index 5660880..f758eeb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,21 @@ "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "5.7.1" + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -52,6 +67,12 @@ "json-schema-traverse": "0.3.1" } }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, "align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", @@ -1343,6 +1364,21 @@ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -1401,6 +1437,12 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1785,6 +1827,16 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.12" + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -1838,6 +1890,43 @@ } } }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1875,6 +1964,15 @@ "path-type": "3.0.0" } }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -1960,6 +2058,30 @@ "is-arrayish": "0.2.1" } }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1997,12 +2119,177 @@ } } }, + "eslint": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.2.0.tgz", + "integrity": "sha512-zlggW1qp7/TBjwLfouRoY7eWXrXwJZFqCdIxxh0/LVB/QuuKuIMkzyUZEcDo6LBadsry5JcEMxIqd3H/66CXVg==", + "dev": true, + "requires": { + "ajv": "6.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "4.0.0", + "eslint-utils": "1.3.1", + "eslint-visitor-keys": "1.0.0", + "espree": "4.0.0", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "4.0.2", + "imurmurhash": "0.1.4", + "inquirer": "5.2.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "string.prototype.matchall": "2.0.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.3", + "text-table": "0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + }, + "ignore": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.2.tgz", + "integrity": "sha512-uoxnT7PYpyEnsja+yX+7v49B7LXxmzDJ2JALqHH3oEGzpM2U1IGcbfnOr8Dt57z3B/UWs7/iAgPFbmye8m4I0g==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "eslint-config-google": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", + "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "4.1.1" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -2509,6 +2796,16 @@ "escape-string-regexp": "1.0.5" } }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -2546,6 +2843,18 @@ "readable-stream": "2.3.6" } }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, "flow-parser": { "version": "0.76.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.76.0.tgz", @@ -2567,6 +2876,12 @@ "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2609,6 +2924,18 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -2904,6 +3231,15 @@ "har-schema": "2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -2939,6 +3275,12 @@ "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", @@ -3200,6 +3542,12 @@ "builtin-modules": "1.1.1" } }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -3209,6 +3557,12 @@ "kind-of": "3.2.2" } }, + "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=", + "dev": true + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -3316,6 +3670,30 @@ } } }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "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.2" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -3357,6 +3735,21 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.3" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -3378,6 +3771,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -3594,6 +3993,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -4435,6 +4840,12 @@ } } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "neo-async": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", @@ -4587,6 +4998,12 @@ } } }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -4919,6 +5336,12 @@ "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", @@ -4987,6 +5410,12 @@ "find-up": "2.1.0" } }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -5035,6 +5464,12 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -5204,6 +5639,21 @@ "safe-regex": "1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "1.1.2" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", @@ -5329,6 +5779,24 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -6069,6 +6537,19 @@ "strip-ansi": "4.0.0" } }, + "string.prototype.matchall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", + "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "regexp.prototype.flags": "1.2.0" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -6120,6 +6601,12 @@ "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": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -6135,6 +6622,55 @@ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", "dev": true }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "6.5.2", + "ajv-keywords": "3.2.0", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + } + } + }, "tapable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", @@ -6499,6 +7035,23 @@ "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", "dev": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -6807,6 +7360,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, "write-file-atomic": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", diff --git a/package.json b/package.json index 61ab2bf..d3f55f9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "test:unit": "truffle migrate --reset && truffle test test/unit/*", "test:integration": "truffle migrate --reset && truffle test test/integration/*", "test": "truffle migrate --reset && truffle test test/unit/* test/integration/*; ", - "coverage": "./node_modules/.bin/solidity-coverage" + "coverage": "./node_modules/.bin/solidity-coverage", + "linter:js": "./node_modules/.bin/eslint test/*", + "linter:js:fix": "./node_modules/.bin/eslint test/* --fix" }, "author": "", "license": "ISC", @@ -18,6 +20,8 @@ }, "devDependencies": { "coveralls": "^3.0.2", + "eslint": "^5.2.0", + "eslint-config-google": "^0.9.1", "solidity-coverage": "^0.5.5" } } diff --git a/test/integration/DPOS.spec.js b/test/integration/DPOS.spec.js index 58b5607..264dee2 100644 --- a/test/integration/DPOS.spec.js +++ b/test/integration/DPOS.spec.js @@ -1,8 +1,7 @@ const TransmuteDPOS = artifacts.require('./TestTransmuteDPOS.sol'); -const { blockMiner, assertFail, roundManagerHelper } = require('../utils.js'); - -contract('integration/TransmuteDPOS', accounts => { +const {blockMiner, assertFail, roundManagerHelper} = require('../utils.js'); +contract('integration/TransmuteDPOS', (accounts) => { let tdpos; let contractAddress; const PROVIDER_POOL_SIZE = 4; @@ -11,28 +10,34 @@ contract('integration/TransmuteDPOS', accounts => { const PROVIDER_UNREGISTERED = 0; const PROVIDER_REGISTERED = 1; - let provider1 = accounts[1]; - let provider2 = accounts[2]; - let provider3 = accounts[3]; - let provider4 = accounts[4]; - let provider5 = accounts[5]; + // Delegator states + const DELEGATOR_UNBONDED = 0; + const DELEGATOR_UNBONDED_WITH_TOKENS_TO_WITHDRAW = 1; + const DELEGATOR_BONDED = 2; + + let provider1; let provider2; let provider3; let provider4; let provider5; + let delegator1; let delegator2; let delegator3; let delegator4; let delegator5; async function reset() { tdpos = await TransmuteDPOS.new(); contractAddress = tdpos.address; - for(let i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { await tdpos.mint(accounts[i], 1000, {from: accounts[0]}); } await tdpos.setMaxNumberOfProviders(PROVIDER_POOL_SIZE); } describe('Registering as Providers', () => { - before(async () => { await reset(); // Make sure that block.number > electionPeriodLength otherwise some tests containing initializeRound might fail // it is ok to do this because in the main network block.number >> 100 await blockMiner.mine(100); + provider1 = accounts[1]; + provider2 = accounts[2]; + provider3 = accounts[3]; + provider4 = accounts[4]; + provider5 = accounts[5]; }); it('provider1 delegates tokens to himself before calling provider()', async () => { @@ -60,7 +65,7 @@ contract('integration/TransmuteDPOS', accounts => { await assertFail( tdpos.initializeRound() ); }); - it("provider2 fails to register because he didn't delegate tokens to himself", async () => { + it('provider2 fails to register because he didn\'t delegate tokens to himself', async () => { await assertFail( tdpos.provider(22, 10, 1, 25, {from: provider2}) ); }); @@ -135,5 +140,116 @@ contract('integration/TransmuteDPOS', accounts => { await assertFail( tdpos.provider(22, 10, 1, 25, {from: provider5}) ); }); }); + + + describe('Bonding tokens', () => { + before(async () => { + await reset(); + provider1 = accounts[1]; + provider2 = accounts[2]; + delegator1 = accounts[3]; + delegator2 = accounts[4]; + delegator3 = accounts[5]; + delegator4 = accounts[6]; + await tdpos.initializeRound(); + // Register provider1 + await tdpos.approve(contractAddress, 100, {from: provider1}); + await tdpos.bond(provider1, 100, {from: provider1}); + await tdpos.provider(22, 10, 1, 25, {from: provider1}); + // Register provider2 + await tdpos.approve(contractAddress, 200, {from: provider2}); + await tdpos.bond(provider2, 200, {from: provider2}); + await tdpos.provider(22, 10, 1, 25, {from: provider2}); + }); + + it('delegator1 fails to delegate his tokens to provider1 because he didn\'t approve the transfer first', async () => { + await assertFail( tdpos.bond(provider1, 100, {from: delegator1}) ); + }); + + it('delegator1 approves the transfer of his tokens', async () => { + await tdpos.approve(contractAddress, 100, {from: delegator1}); + }); + + it('delegator1 delegates his tokens to provider1', async () => { + await tdpos.bond(provider1, 100, {from: delegator1}); + }); + + it('delegator2 fails to delegate to provider1 because amount delegated is zero', async () => { + await tdpos.approve(contractAddress, 100, {from: delegator2}); + await assertFail( tdpos.bond(provider1, 0, {from: delegator2}) ); + }); + + it('delegator2 delegates non zero amount of tokens to provider1', async () => { + await tdpos.bond(provider1, 100, {from: delegator2}); + }); + + it('delegator3 fails to delegate to provider3 because provider3 is not a Registered Provider', async () => { + await tdpos.approve(contractAddress, 100, {from: delegator3}); + await assertFail( tdpos.bond(provider3, 100, {from: delegator3}) ); + }); + + it('delegator3 delegates to provider2', async () => { + await tdpos.bond(provider2, 100, {from: delegator3}); + }); + + it('delegator4 delegates to himself', async () => { + await tdpos.approve(contractAddress, 100, {from: delegator4}); + await tdpos.bond(delegator4, 100, {from: delegator4}); + }); + }); + + describe('Unbonding tokens', () => { + before(async () => { + delegator5 = accounts[7]; + }); + + it('delegator1 unbonds and enters the UNBONDED_WITH_TOKENS_TO_WITHDRAW state', async () => { + assert.equal(DELEGATOR_BONDED, await tdpos.delegatorStatus(delegator1)); + await tdpos.unbond({from: delegator1}); + assert.equal(DELEGATOR_UNBONDED_WITH_TOKENS_TO_WITHDRAW, await tdpos.delegatorStatus(delegator1)); + }); + + it('delegator1 unbonds again but fails because he is in the UNBONDED_WITH_TOKENS_TO_WITHDRAW state', async () => { + assert.equal(DELEGATOR_UNBONDED_WITH_TOKENS_TO_WITHDRAW, await tdpos.delegatorStatus(delegator1)); + await assertFail( tdpos.unbond({from: delegator1}) ); + }); + + it('provider1 unbonds and as a result looses his Provider status', async () => { + assert.equal(PROVIDER_REGISTERED, await tdpos.providerStatus(provider1)); + await tdpos.unbond({from: provider1}); + assert.equal(PROVIDER_UNREGISTERED, await tdpos.providerStatus(provider1)); + }); + + it('delegator5 unbonds but fails because he is in the UNBONDED state', async () => { + assert.equal(DELEGATOR_UNBONDED, await tdpos.delegatorStatus(delegator5)); + await assertFail( tdpos.unbond({from: delegator5}) ); + }); + }); + + describe('Withdrawing tokens', () => { + it('delegator1 withdraws and fails because he didn\'t wait the unbondingPeriod', async () => { + assert.equal(DELEGATOR_UNBONDED_WITH_TOKENS_TO_WITHDRAW, await tdpos.delegatorStatus(delegator1)); + await assertFail( tdpos.withdraw({from: delegator1}) ); + }); + + it('delegator1 waits the unbondingPeriod and withdraws his tokens', async () => { + const withdrawInformation = await tdpos.withdrawInformations.call(delegator1); + const withdrawBlock = withdrawInformation[0]; + await blockMiner.mineUntilBlock(withdrawBlock); + await tdpos.withdraw({from: delegator1}); + assert.equal(DELEGATOR_UNBONDED, await tdpos.delegatorStatus(delegator1)); + }); + + it('provider1 withdraws his tokens and enters UNBONDED state', async () => { + assert.equal(DELEGATOR_UNBONDED_WITH_TOKENS_TO_WITHDRAW, await tdpos.delegatorStatus(provider1)); + await tdpos.withdraw({from: provider1}); + assert.equal(DELEGATOR_UNBONDED, await tdpos.delegatorStatus(provider1)); + }); + + it('delegator4 withdraws but fails because he is in the BONDED state', async () => { + assert.equal(DELEGATOR_BONDED, await tdpos.delegatorStatus(delegator4)); + await assertFail( tdpos.withdraw({from: delegator4}) ); + }); + }); }); diff --git a/test/unit/JobManager.spec.js b/test/unit/JobManager.spec.js index 02e51dd..9456564 100644 --- a/test/unit/JobManager.spec.js +++ b/test/unit/JobManager.spec.js @@ -1,23 +1,21 @@ const JobManager = artifacts.require('./JobManager.sol'); -const { assertFail } = require('../utils.js'); +const {assertFail} = require('../utils.js'); require('truffle-test-utils').init(); -contract('JobManager', accounts => { - +contract('JobManager', (accounts) => { let jm; const MINERAL_COMPUTE = 0; const MINERAL_STORAGE = 1; describe('submitMineral', () => { - before(async () => { jm = await JobManager.deployed(); }); it('should fail if category is not MINERAL_COMPUTE or MINERAL_STORAGE', async () => { - await jm.submitMineral("test", MINERAL_COMPUTE); - await jm.submitMineral("test", MINERAL_STORAGE); - await assertFail( jm.submitMineral("test", 2) ); + await jm.submitMineral('test', MINERAL_COMPUTE); + await jm.submitMineral('test', MINERAL_STORAGE); + await assertFail( jm.submitMineral('test', 2) ); }); it('should store the Mineral in the minerals mapping', async () => { @@ -33,7 +31,7 @@ contract('JobManager', accounts => { it('should increment numberOfMinerals', async () => { const numberOfMinerals = await jm.numberOfMinerals.call(); await jm.submitMineral('addition', MINERAL_COMPUTE); - assert.deepEqual(numberOfMinerals.add(1), await jm.numberOfMinerals.call()) + assert.deepEqual(numberOfMinerals.add(1), await jm.numberOfMinerals.call()); }); it('should emit a MineralAdded event', async () => { @@ -46,28 +44,27 @@ contract('JobManager', accounts => { name: 'division', producer: accounts[0], category: MINERAL_COMPUTE, - } + }, }); }); it('should fail if name is an empty string', async () => { const mineralId = (await jm.numberOfMinerals.call()).toNumber(); - await assertFail( jm.submitMineral("", MINERAL_COMPUTE) ); - await jm.submitMineral("non empty string", MINERAL_COMPUTE); + await assertFail( jm.submitMineral('', MINERAL_COMPUTE) ); + await jm.submitMineral('non empty string', MINERAL_COMPUTE); const mineral = await jm.minerals.call(mineralId); let name = mineral[0]; - assert.equal("non empty string", name); + assert.equal('non empty string', name); }); }); describe('submitJob', () => { - let expirationBlock = web3.eth.blockNumber + 1000; before(async () => { jm = await JobManager.new(); - await jm.submitMineral("multiplication", MINERAL_COMPUTE); - await jm.submitMineral("addition", MINERAL_COMPUTE); + await jm.submitMineral('multiplication', MINERAL_COMPUTE); + await jm.submitMineral('addition', MINERAL_COMPUTE); }); it('should fail if mineralId is not the id of a valid Mineral', async () => { @@ -103,15 +100,15 @@ contract('JobManager', accounts => { id: jobId.toNumber(), mineralId: 1, minPricePerMineral: 12, - expirationBlock: expirationBlock - } + expirationBlock: expirationBlock, + }, }); }); it('should increment numberOfJobs', async () => { const numberOfJobs = await jm.numberOfJobs.call(); await jm.submitJob(1, 12, expirationBlock); - assert.deepEqual(numberOfJobs.add(1), await jm.numberOfJobs.call()) + assert.deepEqual(numberOfJobs.add(1), await jm.numberOfJobs.call()); }); }); }); diff --git a/test/unit/ProviderPool.spec.js b/test/unit/ProviderPool.spec.js index 9435cf3..5cb4fcd 100644 --- a/test/unit/ProviderPool.spec.js +++ b/test/unit/ProviderPool.spec.js @@ -1,11 +1,10 @@ // Here we use the TestProviderPool contract instead of the ProviderPool -// This is to be able to test the addProvider function which has internal visibility +// This is to be able to test the addProvider function which has internal visibility // through the publicAddProvider function from TestProviderPool which has public visibility const ProviderPool = artifacts.require('./TestProviderPool.sol'); -const { blockMiner, assertFail } = require('../utils.js'); - -contract('ProviderPool', accounts => { +const {assertFail} = require('../utils.js'); +contract('ProviderPool', (accounts) => { let pp; async function assertProvidersAreSortedByBondedAmount() { @@ -17,7 +16,7 @@ contract('ProviderPool', accounts => { let currentAddress = providerPool[0]; // [0] is head of the list let node = await pp.getProvider.call(currentAddress); let end = providerPool[1]; // [1] is tail of the list - while(currentAddress != end) { + while (currentAddress != end) { assert(bondedAmountOfPreviousAddress >= node[0]); // [0] is the bondedAmount assert.equal(node[2], previousAddress); // [2] is previous address in the list bondedAmountOfPreviousAddress = node[0].toNumber(); @@ -28,7 +27,6 @@ contract('ProviderPool', accounts => { } describe('setMaxNumberOfProviders', () => { - before(async () => { pp = await ProviderPool.deployed(); }); @@ -41,17 +39,16 @@ contract('ProviderPool', accounts => { assert.equal(7, providerPool[2]); }); - it("should fail if it is not called from the owner's address", async () => { + it('should fail if it is not called from the owner\'s address', async () => { await assertFail( pp.setMaxNumberOfProviders(10, {from: accounts[1]}) ); }); - it("should fail if new size is less than current size", async () => { + it('should fail if new size is less than current size', async () => { await assertFail( pp.setMaxNumberOfProviders(6, {from: accounts[0]}) ); }); }); describe('addProvider', () => { - it('should add a provider to the pool', async () => { let providerPool = await pp.providerPool.call(); assert.equal(0, providerPool[0]); // address head @@ -90,7 +87,6 @@ contract('ProviderPool', accounts => { }); describe('containsProvider', () => { - before(async () => { pp = await ProviderPool.new(); await pp.setMaxNumberOfProviders(10, {from: accounts[0]}); @@ -107,7 +103,6 @@ contract('ProviderPool', accounts => { }); describe('updateProvider', () => { - before(async () => { pp = await ProviderPool.new(); await pp.setMaxNumberOfProviders(10, {from: accounts[0]}); @@ -120,20 +115,22 @@ contract('ProviderPool', accounts => { it('should update the new key', async () => { let provider = await pp.getProvider(accounts[0]); - assert.equal(1, provider[0]); //[0] is the key (ie totalBondedAmount) + let totalBondedAmount = provider[0]; + assert.equal(1, totalBondedAmount); await pp.publicUpdateProvider(accounts[0], 9); provider = await pp.getProvider(accounts[0]); - assert.equal(9, provider[0]); + totalBondedAmount = provider[0]; + assert.equal(9, totalBondedAmount); }); it('should keep the value sorted', async () => { await pp.publicUpdateProvider(accounts[1], 10); - await assertProvidersAreSortedByBondedAmount() + await assertProvidersAreSortedByBondedAmount(); }); it('should maintain the size of the pool constant', async () => { let providerPool = await pp.providerPool.call(); - const previousSize = providerPool[3].toNumber(); // [3] is the current size of the pool + const previousSize = providerPool[3].toNumber(); await pp.publicUpdateProvider(accounts[2], 20); providerPool = await pp.providerPool.call(); assert.equal(previousSize, providerPool[3]); @@ -141,7 +138,7 @@ contract('ProviderPool', accounts => { it('should remove the provider if updated totalBondedAmount is zero', async () => { let providerPool = await pp.providerPool.call(); - const previousSize = providerPool[3].toNumber(); // [3] is the current size of the pool + const previousSize = providerPool[3].toNumber(); assert.equal(true, await pp.containsProvider(accounts[2])); await pp.publicUpdateProvider(accounts[2], 0); assert.equal(false, await pp.containsProvider(accounts[2])); @@ -155,7 +152,6 @@ contract('ProviderPool', accounts => { }); describe('removeProvider', () => { - it('should remove the provider from the pool', async () => { assert.equal(true, await pp.containsProvider(accounts[0])); await pp.publicRemoveProvider(accounts[0]); @@ -164,7 +160,7 @@ contract('ProviderPool', accounts => { it('should decrease the size of the pool by one', async () => { let providerPool = await pp.providerPool.call(); - const previousSize = providerPool[3].toNumber(); // [3] is the current size of the pool + const previousSize = providerPool[3].toNumber(); await pp.publicRemoveProvider(accounts[1]); providerPool = await pp.providerPool.call(); assert.equal(previousSize - 1, providerPool[3]); diff --git a/test/unit/RoundManager.spec.js b/test/unit/RoundManager.spec.js index 60e0e4c..1a8c442 100644 --- a/test/unit/RoundManager.spec.js +++ b/test/unit/RoundManager.spec.js @@ -1,15 +1,13 @@ const RoundManager = artifacts.require('./RoundManager.sol'); -const { blockMiner, assertFail } = require('../utils.js'); - -contract('RoundManager', accounts => { +const {blockMiner, assertFail} = require('../utils.js'); +contract('RoundManager', (accounts) => { let rm; const electionPeriodLength = 20; const rateLockDeadline = 5; const unbondingPeriod = 10; describe('initializeRound', () => { - before(async () => { rm = await RoundManager.deployed(); await rm.setElectionPeriodLength(electionPeriodLength); diff --git a/test/unit/TransmuteDPOS.spec.js b/test/unit/TransmuteDPOS.spec.js index b7bbeae..5997886 100644 --- a/test/unit/TransmuteDPOS.spec.js +++ b/test/unit/TransmuteDPOS.spec.js @@ -1,9 +1,8 @@ const TransmuteDPOS = artifacts.require('./TestTransmuteDPOS.sol'); -const { blockMiner, assertFail, roundManagerHelper } = require('../utils.js'); +const {blockMiner, assertFail, roundManagerHelper} = require('../utils.js'); require('truffle-test-utils').init(); -contract('TransmuteDPOS', accounts => { - +contract('TransmuteDPOS', (accounts) => { let tdpos; let contractAddress; const PROVIDER_POOL_SIZE = 5; @@ -30,7 +29,7 @@ contract('TransmuteDPOS', accounts => { async function initNew() { tdpos = await TransmuteDPOS.new(); contractAddress = tdpos.address; - for(let i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { await tdpos.mint(accounts[i], 1000, {from: accounts[0]}); } await tdpos.setMaxNumberOfProviders(PROVIDER_POOL_SIZE); @@ -40,11 +39,10 @@ contract('TransmuteDPOS', accounts => { } describe('provider', () => { - before(async () => { tdpos = await TransmuteDPOS.deployed(); contractAddress = tdpos.address; - for(let i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { await tdpos.mint(accounts[i], 1000, {from: accounts[0]}); } await tdpos.setMaxNumberOfProviders(PROVIDER_POOL_SIZE); @@ -67,7 +65,7 @@ contract('TransmuteDPOS', accounts => { assert.equal(42, totalBondedAmount); }); - it("should register a Provider's parameters", async () => { + it('should register a Provider\'s parameters', async () => { assert.equal(PROVIDER_UNREGISTERED, await tdpos.providerStatus.call(accounts[1])); await approveBondProvider(10, 20, 2, 35, 1, accounts[1]); const provider = await tdpos.providers.call(accounts[1]); @@ -124,7 +122,7 @@ contract('TransmuteDPOS', accounts => { _pricePerComputeMineral: 10, _blockRewardCut: 1, _feeShare: 25, - } + }, }); }); @@ -138,7 +136,7 @@ contract('TransmuteDPOS', accounts => { _pricePerComputeMineral: 11, _blockRewardCut: 2, _feeShare: 24, - } + }, }); }); @@ -160,18 +158,18 @@ contract('TransmuteDPOS', accounts => { const maxSize = providerPool[2].toNumber(); let currentSize = providerPool[3]; assert.isAbove(maxSize, currentSize.toNumber()); - await approveBondProvider(20 ,10, 2, 25, 1, accounts[4]); + await approveBondProvider(20, 10, 2, 25, 1, accounts[4]); providerPool = await tdpos.providerPool.call(); currentSize = providerPool[3]; assert.equal(maxSize, currentSize); - await assertFail( approveBondProvider(20 ,10, 2, 25, 1, accounts[5]) ); + await assertFail( approveBondProvider(20, 10, 2, 25, 1, accounts[5]) ); }); it('should work if Provider is Registered and size == maxSize', async () => { let provider = await tdpos.providers.call(accounts[4]); pricePerStorageMineral = provider[0]; assert.equal(20, pricePerStorageMineral); - await tdpos.provider(21 ,10, 2, 25, {from: accounts[4]}); + await tdpos.provider(21, 10, 2, 25, {from: accounts[4]}); provider = await tdpos.providers.call(accounts[4]); pricePerStorageMineral = provider[0]; assert.equal(21, pricePerStorageMineral); @@ -179,7 +177,6 @@ contract('TransmuteDPOS', accounts => { }); describe('resignAsProvider', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -188,7 +185,6 @@ contract('TransmuteDPOS', accounts => { }); it('should remove the Provider from the provider mapping', async () => { - const registeredProvider = await tdpos.providers.call(accounts[0]); let providerStatus = await tdpos.providerStatus.call(accounts[0]); assert.equal(PROVIDER_REGISTERED, providerStatus); await tdpos.publicResignAsProvider(accounts[0]); @@ -216,17 +212,16 @@ contract('TransmuteDPOS', accounts => { event: 'ProviderResigned', args: { _provider: accounts[2], - } + }, }); }); - it("should fail if the transaction's sender is not a Provider", async () => { + it('should fail if the transaction\'s sender is not a Provider', async () => { await assertFail( tdpos.publicResignAsProvider(accounts[3]) ); }); }); describe('bond', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -261,12 +256,12 @@ contract('TransmuteDPOS', accounts => { }); it('should fail if the address is not a registered Provider address', async () => { - await tdpos.approve(contractAddress, 15, {from: accounts[7]}) + await tdpos.approve(contractAddress, 15, {from: accounts[7]}); await assertFail( tdpos.bond(accounts[2], 15, {from: accounts[7]}) ); }); it('should work if the address is not a registered Provider address but the address is the sender address', async () => { - await tdpos.approve(contractAddress, 15, {from: accounts[3]}) + await tdpos.approve(contractAddress, 15, {from: accounts[3]}); await tdpos.bond(accounts[3], 15, {from: accounts[3]}); }); @@ -278,13 +273,13 @@ contract('TransmuteDPOS', accounts => { it('should fail if TST balance is less than bonded amount', async () => { await tdpos.approve(contractAddress, 1001, {from: accounts[9]}); - await assertFail( tdpos.bond(accounts[1], 1001, {from: accounts[9]}) ) + await assertFail( tdpos.bond(accounts[1], 1001, {from: accounts[9]}) ); const provider = await tdpos.providers.call(accounts[1]); const totalAmountBonded = provider[4]; assert(1001 >= totalAmountBonded); }); - it("should transfer amount from the Delegator's balance to the contract's balance", async () => { + it('should transfer amount from the Delegator\'s balance to the contract\'s balance', async () => { const contractBalance = (await tdpos.balanceOf(tdpos.address)).toNumber(); assert.equal(1000, await tdpos.balanceOf(accounts[9])); await tdpos.bond(accounts[1], 300, {from: accounts[9]}); @@ -316,14 +311,13 @@ contract('TransmuteDPOS', accounts => { args: { _delegator: accounts[4], _provider: accounts[0], - _amount: 300 - } + _amount: 300, + }, }); }); }); describe('unbond', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -343,7 +337,7 @@ contract('TransmuteDPOS', accounts => { await assertFail( tdpos.unbond({from: accounts[9]}) ); }); - it("should set withdrawInformation for the Delegator's address", async () => { + it('should set withdrawInformation for the Delegator\'s address', async () => { let withdrawInformation = await tdpos.withdrawInformations.call(accounts[2]); let withdrawBlock = withdrawInformation[0]; assert.equal(0, withdrawBlock); @@ -393,14 +387,13 @@ contract('TransmuteDPOS', accounts => { args: { _delegator: accounts[5], _provider: accounts[0], - _amount: 300 - } + _amount: 300, + }, }); }); }); describe('delegatorStatus', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -439,7 +432,6 @@ contract('TransmuteDPOS', accounts => { }); describe('providerStatus', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -460,7 +452,6 @@ contract('TransmuteDPOS', accounts => { }); describe('withdraw', () => { - before(async () => { await initNew(); await approveBondProvider(22, 10, 1, 25, 1, accounts[0]); @@ -502,7 +493,7 @@ contract('TransmuteDPOS', accounts => { await blockMiner.mineUntilBlock(withdrawBlock - 1); await tdpos.withdraw({from: accounts[3]}); const newBalance = await tdpos.balanceOf(accounts[3]); - assert.equal(previousBalance.plus(300).toNumber(), await tdpos.balanceOf(accounts[3])); + assert.equal(previousBalance.plus(300).toNumber(), newBalance); }); it('should switch Delegator status to Unbonded', async () => { diff --git a/test/unit/TransmuteToken.spec.js b/test/unit/TransmuteToken.spec.js index 4546692..19af028 100644 --- a/test/unit/TransmuteToken.spec.js +++ b/test/unit/TransmuteToken.spec.js @@ -2,8 +2,8 @@ const TST = artifacts.require('./TransmuteToken.sol'); const utils = require('../utils.js'); const assertFail = utils.assertFail; -contract('TST', accounts => { - let owner, tst; +contract('TST', (accounts) => { + let owner; let tst; const tokenAmount = 1000; it('has the correct owner', async () => { @@ -21,7 +21,7 @@ contract('TST', accounts => { assert(tokenAmount === (await tst.balanceOf.call(accounts[1])).toNumber()); }); - it('only owner can mint new tokens', async() => { + it('only owner can mint new tokens', async () => { await assertFail( tst.mint(owner, tokenAmount, {from: accounts[1]}), 'this account should not be able to mint tokens' @@ -49,12 +49,12 @@ contract('TST', accounts => { assert(approvedAmount <= (await tst.balanceOf(accounts[2])).toNumber()); await tst.approve(accounts[4], approvedAmount, {from: accounts[2]}); await assertFail( - tst.transferFrom(accounts[2], accounts[3], approvedAmount + 1 , {from: accounts[4]}), + tst.transferFrom(accounts[2], accounts[3], approvedAmount + 1, {from: accounts[4]}), 'should not be able to transfer more tokens than what was approved' ); }); - it('owner cannot mint new token after finishMinting is called', async() => { + it('owner cannot mint new token after finishMinting is called', async () => { await tst.finishMinting({from: owner}); await assertFail( tst.mint(owner, tokenAmount, {from: owner}), diff --git a/test/utils.js b/test/utils.js index 7a042a9..940c824 100644 --- a/test/utils.js +++ b/test/utils.js @@ -3,7 +3,10 @@ class RoundManagerHelper { async getElectionPeriodEndBlock(roundManager) { const startOfCurrentRound = await roundManager.startOfCurrentRound.call(); const electionPeriodLength = await roundManager.electionPeriodLength.call(); - return startOfCurrentRound.add(electionPeriodLength).sub(1).toNumber(); + return startOfCurrentRound + .add(electionPeriodLength) + .sub(1) + .toNumber(); } // At that block, a provider can no longer update his parameters @@ -11,7 +14,10 @@ class RoundManagerHelper { const startOfCurrentRound = await roundManager.startOfCurrentRound.call(); const electionPeriodLength = await roundManager.electionPeriodLength.call(); const rateLockDeadline = await roundManager.rateLockDeadline.call(); - return startOfCurrentRound.add(electionPeriodLength).sub(rateLockDeadline).sub(1); + return startOfCurrentRound + .add(electionPeriodLength) + .sub(rateLockDeadline) + .sub(1); } } @@ -19,9 +25,9 @@ module.exports.roundManagerHelper = new RoundManagerHelper(); class BlockMiner { async mine(numberOfBlocks) { - for(let i = 0; i < numberOfBlocks; i++) { + for (let i = 0; i < numberOfBlocks; i++) { await new Promise((resolve, _) => { - web3.currentProvider.sendAsync({ method: "evm_mine", id: i }, resolve); + web3.currentProvider.sendAsync({method: 'evm_mine', id: i}, resolve); }); } } @@ -38,12 +44,13 @@ module.exports.assertFail = async (promise, message) => { try { await promise; assert(false); - } catch(e) { + } catch (e) { if (e.name == 'AssertionError') { - if (message) + if (message) { assert(false, message); - else + } else { assert(false); + } } } -} +}; diff --git a/truffle-config.js b/truffle-config.js index 2a436aa..2c4d1ba 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -1,4 +1,3 @@ - const Web3 = require('web3'); module.exports = { @@ -6,7 +5,7 @@ module.exports = { networks: { development: { provider: new Web3.providers.HttpProvider('http://localhost:8545'), - network_id: '*' // Match any network id - } - } + network_id: '*', // Match any network id + }, + }, };