diff --git a/contracts/ERC1271Sample.sol b/contracts/ERC1271Sample.sol new file mode 100644 index 0000000..655f022 --- /dev/null +++ b/contracts/ERC1271Sample.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.5.16; + +import "./IERC1271.sol"; + +// libraries +import "@openzeppelin/contracts/ownership/Ownable.sol"; + +/** + * @notice ERC-1271: Standard Signature Validation Method for Contracts + */ +contract ERC1271Sample is ERC1271, Ownable { + + // bytes4(keccak256("isValidSignature(bytes32,bytes)") + bytes4 constant internal MAGICVALUE = 0x1626ba7e; + + // To store the Data Hash => Singature Hash + mapping(bytes32 => bytes32) public signatures; + + /** + * @dev Should return whether the signature provided is valid for the provided data + * @param _hash Arbitrary length data signed on the behalf of address(this) + * @param _signature Signature byte array associated with _hash + * + * MUST return the bytes4 magic value 0x1626ba7e when function passes. + * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) + * MUST allow external calls + */ + function isValidSignature( + bytes32 _hash, + bytes memory _signature) + public + view + returns (bytes4 magicValue) { + if(signatures[_hash] == keccak256(_signature)) + return MAGICVALUE; + return 0; + } + + function addSignature( + bytes32 _hash, + bytes memory _signature) + public + onlyOwner { + signatures[_hash] = keccak256(_signature); + } + + function addSignature( + bytes32 _hash, + bytes32 _signatureHash) + public + onlyOwner { + signatures[_hash] = _signatureHash; + } +} \ No newline at end of file diff --git a/contracts/EthereumDIDRegistry.sol b/contracts/EthereumDIDRegistry.sol index f0afbb4..e802a65 100644 --- a/contracts/EthereumDIDRegistry.sol +++ b/contracts/EthereumDIDRegistry.sol @@ -1,6 +1,13 @@ -pragma solidity ^0.4.4; +pragma solidity ^0.5.16; + +import "./IERC1271.sol"; + +// libraries +import "@openzeppelin/contracts/cryptography/ECDSA.sol"; contract EthereumDIDRegistry { + + bytes4 internal constant _ERC1271_MAGICVALUE = 0x1626ba7e; mapping(address => address) public owners; mapping(address => mapping(bytes32 => mapping(address => uint))) public delegates; @@ -36,7 +43,7 @@ contract EthereumDIDRegistry { function identityOwner(address identity) public view returns(address) { address owner = owners[identity]; - if (owner != 0x0) { + if (owner != address(0x0)) { return owner; } return identity; @@ -49,8 +56,41 @@ contract EthereumDIDRegistry { return signer; } + /** + * @notice Checks if an identity's owner had provided a valid `_signature` for `_hash`. + * If the identity's owner is a smart contract, the 'isValidSignature' will be called accourding to ERC1271 interface. + * + * @param _hash hash of the data signed//Arbitrary length data signed on the behalf of `identity` + * @param _signature identity's signature(s) of the data + */ + function checkSignature( + address identity, + bytes32 _hash, + bytes memory _signature + ) internal returns (address) { + address owner = identityOwner(identity); + bool isContract; + // solium-disable-next-line security/no-inline-assembly + assembly { + isContract := gt(extcodesize(owner), 0) + } + if (isContract) { + require( + _ERC1271_MAGICVALUE == + ERC1271(owner).isValidSignature(_hash, _signature) + ); + nonce[owner]++; + return owner; + } else { + address signer = ECDSA.recover(_hash, _signature); + require(signer == identityOwner(identity)); + nonce[signer]++; + return signer; + } + } + function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns(bool) { - uint validity = delegates[identity][keccak256(delegateType)][delegate]; + uint validity = delegates[identity][keccak256(abi.encodePacked(delegateType))][delegate]; return (validity > now); } @@ -65,12 +105,17 @@ contract EthereumDIDRegistry { } function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public { - bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "changeOwner", newOwner); + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "changeOwner", newOwner)); changeOwner(identity, checkSignature(identity, sigV, sigR, sigS, hash), newOwner); } + function changeOwnerSigned(address identity, bytes memory signature, address newOwner) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "changeOwner", newOwner)); + changeOwner(identity, checkSignature(identity, hash, signature), newOwner); + } + function addDelegate(address identity, address actor, bytes32 delegateType, address delegate, uint validity) internal onlyOwner(identity, actor) { - delegates[identity][keccak256(delegateType)][delegate] = now + validity; + delegates[identity][keccak256(abi.encodePacked(delegateType))][delegate] = now + validity; emit DIDDelegateChanged(identity, delegateType, delegate, now + validity, changed[identity]); changed[identity] = block.number; } @@ -80,12 +125,17 @@ contract EthereumDIDRegistry { } function addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate, uint validity) public { - bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "addDelegate", delegateType, delegate, validity); + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "addDelegate", delegateType, delegate, validity)); addDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate, validity); } + function addDelegateSigned(address identity, bytes memory signature, bytes32 delegateType, address delegate, uint validity) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "addDelegate", delegateType, delegate, validity)); + addDelegate(identity, checkSignature(identity, hash, signature), delegateType, delegate, validity); + } + function revokeDelegate(address identity, address actor, bytes32 delegateType, address delegate) internal onlyOwner(identity, actor) { - delegates[identity][keccak256(delegateType)][delegate] = now; + delegates[identity][keccak256(abi.encodePacked(delegateType))][delegate] = now; emit DIDDelegateChanged(identity, delegateType, delegate, now, changed[identity]); changed[identity] = block.number; } @@ -95,36 +145,51 @@ contract EthereumDIDRegistry { } function revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate) public { - bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeDelegate", delegateType, delegate); + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeDelegate", delegateType, delegate)); revokeDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate); } - function setAttribute(address identity, address actor, bytes32 name, bytes value, uint validity ) internal onlyOwner(identity, actor) { + function revokeDelegateSigned(address identity, bytes memory signature, bytes32 delegateType, address delegate) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeDelegate", delegateType, delegate)); + revokeDelegate(identity, checkSignature(identity, hash, signature), delegateType, delegate); + } + + function setAttribute(address identity, address actor, bytes32 name, bytes memory value, uint validity ) internal onlyOwner(identity, actor) { emit DIDAttributeChanged(identity, name, value, now + validity, changed[identity]); changed[identity] = block.number; } - function setAttribute(address identity, bytes32 name, bytes value, uint validity) public { + function setAttribute(address identity, bytes32 name, bytes memory value, uint validity) public { setAttribute(identity, msg.sender, name, value, validity); } - function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value, uint validity) public { - bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "setAttribute", name, value, validity); + function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes memory value, uint validity) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "setAttribute", name, value, validity)); setAttribute(identity, checkSignature(identity, sigV, sigR, sigS, hash), name, value, validity); } - function revokeAttribute(address identity, address actor, bytes32 name, bytes value ) internal onlyOwner(identity, actor) { + function setAttributeSigned(address identity, bytes memory signature, bytes32 name, bytes memory value, uint validity) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "setAttribute", name, value, validity)); + setAttribute(identity, checkSignature(identity, hash, signature), name, value, validity); + } + + function revokeAttribute(address identity, address actor, bytes32 name, bytes memory value ) internal onlyOwner(identity, actor) { emit DIDAttributeChanged(identity, name, value, 0, changed[identity]); changed[identity] = block.number; } - function revokeAttribute(address identity, bytes32 name, bytes value) public { + function revokeAttribute(address identity, bytes32 name, bytes memory value) public { revokeAttribute(identity, msg.sender, name, value); } - function revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value) public { - bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeAttribute", name, value); + function revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes memory value) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeAttribute", name, value)); revokeAttribute(identity, checkSignature(identity, sigV, sigR, sigS, hash), name, value); } + function revokeAttributeSigned(address identity, bytes memory signature, bytes32 name, bytes memory value) public { + bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "revokeAttribute", name, value)); + revokeAttribute(identity, checkSignature(identity, hash, signature), name, value); + } + } diff --git a/contracts/IERC1271.sol b/contracts/IERC1271.sol new file mode 100644 index 0000000..ce06bb7 --- /dev/null +++ b/contracts/IERC1271.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.5.16; + +/** + * @notice ERC-1271: Standard Signature Validation Method for Contracts + */ +contract ERC1271 { + + // bytes4(keccak256("isValidSignature(bytes32,bytes)") + bytes4 constant internal MAGICVALUE = 0x1626ba7e; + + /** + * @dev Should return whether the signature provided is valid for the provided data + * @param _hash Arbitrary length data signed on the behalf of address(this) + * @param _signature Signature byte array associated with _hash + * + * MUST return the bytes4 magic value 0x1626ba7e when function passes. + * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) + * MUST allow external calls + */ + function isValidSignature( + bytes32 _hash, + bytes memory _signature) + public + view + returns (bytes4 magicValue); +} \ No newline at end of file diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index f170cb4..3ec8e03 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.17; +pragma solidity ^0.5.16; contract Migrations { address public owner; @@ -8,7 +8,7 @@ contract Migrations { if (msg.sender == owner) _; } - function Migrations() public { + constructor() public { owner = msg.sender; } diff --git a/migrations/2_erc1271_sample.js b/migrations/2_erc1271_sample.js new file mode 100644 index 0000000..6b5d58c --- /dev/null +++ b/migrations/2_erc1271_sample.js @@ -0,0 +1,6 @@ +var ERC1271Sample = artifacts.require("ERC1271Sample"); + +module.exports = function(deployer) { + // deployment steps + deployer.deploy(ERC1271Sample); +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1b44417..1f6b67d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,17 @@ "js-tokens": "^4.0.0" } }, + "@openzeppelin/contracts": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-2.5.1.tgz", + "integrity": "sha512-qIy6tLx8rtybEsIOAlrM4J/85s2q2nPkDqj/Rx46VakBZ0LwtFhXIVub96LXHczQX0vaqmAueDqNPXtbSXSaYQ==" + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "acorn": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", @@ -48,6 +59,12 @@ "uri-js": "^4.2.2" } }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -81,6 +98,22 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", "dev": true }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -90,6 +123,18 @@ "sprintf-js": "~1.0.2" } }, + "array.prototype.map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", + "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.4" + } + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -102,6 +147,12 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -136,6 +187,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -143,9 +203,9 @@ "dev": true }, "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "browserify-aes": { @@ -175,9 +235,9 @@ "dev": true }, "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "chalk": { @@ -197,6 +257,22 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -223,59 +299,44 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -364,10 +425,19 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "dir-to-object": { @@ -418,13 +488,55 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, "escape-string-regexp": { @@ -696,14 +808,32 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "is-buffer": "~2.0.3" } }, "flat-cache": { @@ -723,25 +853,25 @@ "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": 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", @@ -1128,9 +1258,9 @@ } }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "glob": { @@ -1147,30 +1277,48 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "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-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -1192,9 +1340,9 @@ } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "hmac-drbg": { @@ -1208,12 +1356,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1299,16 +1441,43 @@ } } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { @@ -1317,28 +1486,85 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", "dev": true }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "isexe": { @@ -1347,6 +1573,22 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "iterate-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", + "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, "js-sha3": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.7.0.tgz", @@ -1381,15 +1623,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "keccak": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", @@ -1402,24 +1635,6 @@ "safe-buffer": "^5.1.0" } }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -1430,17 +1645,13 @@ "type-check": "~0.3.2" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "p-locate": "^5.0.0" } }, "lodash": { @@ -1449,11 +1660,66 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "ls": { "version": "0.2.1", @@ -1475,12 +1741,6 @@ "safe-buffer": "^5.1.2" } }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true - }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -1524,42 +1784,48 @@ } }, "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.2.tgz", + "integrity": "sha512-I8FRAcuACNMLQn3lS4qeWLxXqLvGf6r2CaLstDpZmMUUSmvW6Cnm1AuHxgbc7ctZVRcfwspCRbDHymPsi3dkJw==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.4.2", + "debug": "4.1.1", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.2", + "object.assign": "4.1.0", + "promise.allsettled": "1.0.2", + "serialize-javascript": "4.0.0", + "strip-json-comments": "3.0.1", + "supports-color": "7.1.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.0", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.1" }, "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1571,24 +1837,49 @@ } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "has-flag": "^2.0.0" + "isexe": "^2.0.0" } } } @@ -1623,24 +1914,36 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1679,21 +1982,36 @@ "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1710,23 +2028,11 @@ "dev": true, "optional": true }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -1746,44 +2052,12 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -1860,31 +2134,41 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise.allsettled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", + "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.1", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "iterate-value": "^1.0.0" + } + }, "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 }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "safe-buffer": "^5.1.0" } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "picomatch": "^2.2.1" } }, "regexpp": { @@ -1899,27 +2183,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true - }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2033,6 +2302,15 @@ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -2081,19 +2359,6 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "solc": { - "version": "0.4.25", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.25.tgz", - "integrity": "sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg==", - "dev": true, - "requires": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" - } - }, "solhint": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.5.1.tgz", @@ -2135,38 +2400,6 @@ "dev": true, "optional": true }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2183,6 +2416,26 @@ "strip-ansi": "^4.0.0" } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2192,15 +2445,6 @@ "ansi-regex": "^3.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -2286,15 +2530,24 @@ "os-tmpdir": "~1.0.2" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "truffle": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.15.tgz", - "integrity": "sha512-6gaNn9ZjvNjdalJMF/qEDUDoRdieKfdYcyFVpVxd+ogAta5kgJxI3XlEmS79Ih0vBhb00tKa9rBweVJ5892sYg==", + "version": "5.1.43", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-5.1.43.tgz", + "integrity": "sha512-KXda/70RAG9TBdQta8JEwVQmL9r/AZzU++5aZkrF4/nDosund8SV1yM9CcDTib4xLWuMaB15YyOC5r163QdLAw==", "dev": true, "requires": { - "mocha": "^4.1.0", - "original-require": "1.0.1", - "solc": "0.4.25" + "app-module-path": "^2.2.0", + "mocha": "8.1.2", + "original-require": "1.0.1" } }, "truffle-hdwallet-provider": { @@ -2341,16 +2594,6 @@ "punycode": "^2.1.0" } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "websocket": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz", @@ -2390,16 +2633,19 @@ } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "wordwrap": { "version": "1.0.0", @@ -2407,49 +2653,47 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "workerpool": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", + "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "dev": true + }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } @@ -2470,9 +2714,9 @@ } }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yaeti": { @@ -2482,72 +2726,215 @@ "dev": true }, "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "locate-path": "^3.0.0" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } }, "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", + "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", + "flat": "^4.1.0", + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } } } diff --git a/package.json b/package.json index 050c07a..5ebda93 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "directories": { "test": "test" }, - "dependencies": {}, + "dependencies": { + "@openzeppelin/contracts": "^2.3.0" + }, "devDependencies": { "ethereumjs-tx": "^1.3.4", "ethereumjs-util": "^5.1.5", @@ -14,7 +16,7 @@ "js-sha3": "^0.7.0", "ls": "^0.2.1", "solhint": "^1.1.10", - "truffle": "^4.1.6", + "truffle": "^5.1.43", "truffle-hdwallet-provider": "^1.0.6" }, "scripts": { diff --git a/test/ethereum_did_registry.js b/test/ethereum_did_registry.js index d312376..2113d6e 100644 --- a/test/ethereum_did_registry.js +++ b/test/ethereum_did_registry.js @@ -1,35 +1,40 @@ var ethutil = require("ethereumjs-util"); var sha3 = require("js-sha3").keccak_256; var EthereumDIDRegistry = artifacts.require("./EthereumDIDRegistry.sol"); +var ERC1271Sample = artifacts.require("./ERC1271Sample.sol"); var BN = require("bn.js"); contract("EthereumDIDRegistry", function(accounts) { let didReg; - const identity = accounts[0]; + let erc1271Sample1; + let erc1271Sample2; + const identity = web3.utils.toChecksumAddress(accounts[0]); let owner; let previousChange; - const identity2 = accounts[1]; - const delegate = accounts[2]; - const delegate2 = accounts[3]; - const delegate3 = accounts[4]; - const delegate4 = accounts[5]; - const badboy = accounts[9]; + const identity2 = web3.utils.toChecksumAddress(accounts[1]); + const delegate = web3.utils.toChecksumAddress(accounts[2]); + const delegate2 = web3.utils.toChecksumAddress(accounts[3]); + const delegate3 = web3.utils.toChecksumAddress(accounts[4]); + const delegate4 = web3.utils.toChecksumAddress(accounts[5]); + const badboy = web3.utils.toChecksumAddress(accounts[9]); const privateKey = Buffer.from( "a285ab66393c5fdda46d6fbad9e27fafd438254ab72ad5acb681a0e9f20f5d7b", "hex" ); - const signerAddress = "0x2036c6cd85692f0fb2c26e6c6b2eced9e4478dfd"; + const signerAddress = web3.utils.toChecksumAddress("0x2036c6cd85692f0fb2c26e6c6b2eced9e4478dfd"); const privateKey2 = Buffer.from( "a285ab66393c5fdda46d6fbad9e27fafd438254ab72ad5acb681a0e9f20f5d7a", "hex" ); - const signerAddress2 = "0xea91e58e9fa466786726f0a947e8583c7c5b3185"; + const signerAddress2 = web3.utils.toChecksumAddress("0xea91e58e9fa466786726f0a947e8583c7c5b3185"); // console.log({identity,identity2, delegate, delegate2, badboy}) before(async () => { didReg = await EthereumDIDRegistry.deployed(); + erc1271Sample1 = await ERC1271Sample.deployed(); + erc1271Sample2 = await ERC1271Sample.new(); }); function getBlock(blockNumber) { return new Promise((resolve, reject) => { @@ -81,18 +86,55 @@ contract("EthereumDIDRegistry", function(accounts) { data; const hash = Buffer.from(sha3.buffer(Buffer.from(dataToSign, "hex"))); const signature = ethutil.ecsign(hash, key); + + // Had to compose the signature manually because + // calling `web3.eth.accounts.sign(hash, key).signature` + // or `await web3.eth.sign("0x" +hash.toString("hex"), signer)` (after adding the key with `web3.eth.accounts.wallet.add("0x" +key.toString("hex"))`) + // both provided a dirrerent signature. + const composedSignature = "0x" + signature.r.toString("hex") + signature.s.toString("hex") + web3.utils.toHex(signature.v).substring(2) + + erc1271Sample1.addSignature(hash, composedSignature) + const publicKey = ethutil.ecrecover( hash, signature.v, signature.r, signature.s - ); + ); return { r: "0x" + signature.r.toString("hex"), s: "0x" + signature.s.toString("hex"), - v: signature.v + v: signature.v, + signature: composedSignature, }; } + async function addContractSignature(identity, ownerERC1271Instance, data) { + // // The next `key` is an arbitrary value because the sample ERC1271 contract + // // Accept any data + // const key = privateKey; + + const signer = ownerERC1271Instance.address; + const nonce = await didReg.nonce(signer); + const paddedNonce = leftPad(Buffer.from([nonce], 64).toString("hex")); + const dataToSign = + "1900" + + stripHexPrefix(didReg.address) + + paddedNonce + + stripHexPrefix(identity) + + data; + const hash = Buffer.from(sha3.buffer(Buffer.from(dataToSign, "hex"))); + + // We can use any signature as a signature here because the ERC1271Sample + // accepts any signature as signature as long as it is provided by the contract owner + const genRanHex = size => "0x"+ [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join(''); + const randomSignature = genRanHex(32); + + ownerERC1271Instance.addSignature(hash, randomSignature); + + return { + signature: randomSignature, + }; + } describe("identityOwner()", () => { describe("default owner", () => { @@ -173,7 +215,7 @@ contract("EthereumDIDRegistry", function(accounts) { }); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -189,7 +231,7 @@ contract("EthereumDIDRegistry", function(accounts) { }); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -235,6 +277,81 @@ contract("EthereumDIDRegistry", function(accounts) { }); }); }); + describe("using composed signature", () => { + describe("as current owner", () => { + let tx; + const newOwner = signerAddress; + before(async () => { + const sig = await signData( + signerAddress2, + signerAddress2, + privateKey2, + Buffer.from("changeOwner").toString("hex") + + stripHexPrefix(newOwner) + ); + tx = await didReg.methods['changeOwnerSigned(address,bytes,address)']( + signerAddress2, + sig.signature, + newOwner, + { from: badboy } + ); + }); + it("should change owner mapping", async () => { + const owner2 = await didReg.owners(signerAddress2); + assert.equal(owner2, newOwner); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(signerAddress2); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDOwnerChanged event", () => { + const event = tx.logs[0]; + // console.log(event.args) + assert.equal(event.event, "DIDOwnerChanged"); + assert.equal(event.args.identity, signerAddress2); + assert.equal(event.args.owner, newOwner); + assert.equal(event.args.previousChange.toNumber(), 0); + }); + }); + }); + describe("using smart contract signature", () => { + describe("as current owner", () => { + let tx; + const identityAddress = ERC1271Sample.address; + let newOwner; + before(async () => { + newOwner = erc1271Sample2.address; + const sig = await addContractSignature( + identityAddress, + erc1271Sample1, + Buffer.from("changeOwner").toString("hex") + + stripHexPrefix(newOwner) + ); + tx = await didReg.methods['changeOwnerSigned(address,bytes,address)']( + identityAddress, + sig.signature, + newOwner, + { from: badboy } + ); + }); + it("should change owner mapping", async () => { + const owner2 = await didReg.owners(identityAddress); + assert.equal(owner2, newOwner); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDOwnerChanged event", () => { + const event = tx.logs[0]; + // console.log(event.args) + assert.equal(event.event, "DIDOwnerChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(event.args.owner, newOwner); + assert.equal(event.args.previousChange.toNumber(), 0); + }); + }); + }); }); describe("addDelegate()", () => { @@ -242,7 +359,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be false", async () => { const valid = await didReg.validDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), delegate3 ); assert.equal(valid, false, "not yet assigned delegate correctly"); @@ -254,7 +371,7 @@ contract("EthereumDIDRegistry", function(accounts) { previousChange = await didReg.changed(identity); tx = await didReg.addDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), delegate3, 86400, { from: delegate2 } @@ -264,7 +381,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be true", async () => { const valid = await didReg.validDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), delegate3 ); assert.equal(valid, true, "assigned delegate correctly"); @@ -292,14 +409,14 @@ contract("EthereumDIDRegistry", function(accounts) { try { const tx = await didReg.addDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), badboy, 86400, { from: badboy } ); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -326,12 +443,12 @@ contract("EthereumDIDRegistry", function(accounts) { stripHexPrefix(delegate) + leftPad(new BN(86400).toString(16)) ); - tx1 = await didReg.addDelegateSigned( + tx1 = await didReg.methods['addDelegateSigned(address,uint8,bytes32,bytes32,bytes32,address,uint256)']( signerAddress, sig.v, sig.r, sig.s, - "attestor", + web3.utils.asciiToHex("attestor"), delegate, 86400, { from: badboy } @@ -341,7 +458,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be true", async () => { let valid = await didReg.validDelegate( signerAddress, - "attestor", + web3.utils.asciiToHex("attestor"), delegate ); assert.equal(valid, true, "assigned delegate correctly"); @@ -364,6 +481,114 @@ contract("EthereumDIDRegistry", function(accounts) { }); }); }); + describe("using composed signature", () => { + describe("as current owner", () => { + let tx1; + let block1; + let previousChange1; + const delegateType = "attestor"; + const identityAddress = signerAddress; + const owner = signerAddress2; + before(async () => { + previousChange1 = await didReg.changed(identityAddress); + let sig = await signData( + identityAddress, + owner, + privateKey2, + Buffer.from("addDelegate").toString("hex") + + stringToBytes32(delegateType) + + stripHexPrefix(delegate) + + leftPad(new BN(86400).toString(16)) + ); + tx1 = await didReg.methods['addDelegateSigned(address,bytes,bytes32,address,uint256)']( + identityAddress, + sig.signature, + web3.utils.asciiToHex(delegateType), + delegate, + 86400, + { from: badboy } + ); + block1 = await getBlock(tx1.receipt.blockNumber); + }); + it("validDelegate should be true", async () => { + let valid = await didReg.validDelegate( + identityAddress, + web3.utils.asciiToHex(delegateType), + delegate + ); + assert.equal(valid, true, "assigned delegate correctly"); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest.toNumber(), tx1.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + let event = tx1.logs[0]; + assert.equal(event.event, "DIDDelegateChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(bytes32ToString(event.args.delegateType), delegateType); + assert.equal(event.args.delegate, delegate); + assert.equal(event.args.validTo.toNumber(), block1.timestamp + 86400); + assert.equal( + event.args.previousChange.toNumber(), + previousChange1.toNumber() + ); + }); + }); + }); + describe("using smart contract signature", () => { + describe("as current owner", () => { + let tx1; + let block1; + let previousChange1; + const identityAddress = ERC1271Sample.address; + const delegateType = "attestor"; + before(async () => { + previousChange1 = await didReg.changed(identityAddress); + let sig = await addContractSignature( + identityAddress, + erc1271Sample2, + Buffer.from("addDelegate").toString("hex") + + stringToBytes32(delegateType) + + stripHexPrefix(delegate) + + leftPad(new BN(86400).toString(16)) + ); + tx1 = await didReg.methods['addDelegateSigned(address,bytes,bytes32,address,uint256)']( + identityAddress, + sig.signature, + web3.utils.asciiToHex(delegateType), + delegate, + 86400, + { from: badboy } + ); + block1 = await getBlock(tx1.receipt.blockNumber); + }); + it("validDelegate should be true", async () => { + let valid = await didReg.validDelegate( + identityAddress, + web3.utils.asciiToHex(delegateType), + delegate + ); + assert.equal(valid, true, "assigned delegate correctly"); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest.toNumber(), tx1.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + let event = tx1.logs[0]; + assert.equal(event.event, "DIDDelegateChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(bytes32ToString(event.args.delegateType), delegateType); + assert.equal(event.args.delegate, delegate); + assert.equal(event.args.validTo.toNumber(), block1.timestamp + 86400); + assert.equal( + event.args.previousChange.toNumber(), + previousChange1.toNumber() + ); + }); + }); + }); }); describe("revokeDelegate()", () => { @@ -371,7 +596,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be true", async () => { const valid = await didReg.validDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), delegate3 ); assert.equal(valid, true, "not yet revoked"); @@ -381,7 +606,7 @@ contract("EthereumDIDRegistry", function(accounts) { let block; before(async () => { previousChange = await didReg.changed(identity); - tx = await didReg.revokeDelegate(identity, "attestor", delegate3, { + tx = await didReg.revokeDelegate(identity, web3.utils.asciiToHex("attestor"), delegate3, { from: delegate2 }); block = await getBlock(tx.receipt.blockNumber); @@ -389,7 +614,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be false", async () => { const valid = await didReg.validDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), delegate3 ); assert.equal(valid, false, "revoked correctly"); @@ -419,13 +644,13 @@ contract("EthereumDIDRegistry", function(accounts) { try { const tx = await didReg.revokeDelegate( identity, - "attestor", + web3.utils.asciiToHex("attestor"), badboy, { from: badboy } ); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -451,7 +676,7 @@ contract("EthereumDIDRegistry", function(accounts) { sig.v, sig.r, sig.s, - "attestor", + web3.utils.asciiToHex("attestor"), delegate, { from: badboy } ); @@ -460,7 +685,7 @@ contract("EthereumDIDRegistry", function(accounts) { it("validDelegate should be false", async () => { const valid = await didReg.validDelegate( signerAddress, - "attestor", + web3.utils.asciiToHex("attestor"), delegate ); assert.equal(valid, false, "revoked delegate correctly"); @@ -486,6 +711,110 @@ contract("EthereumDIDRegistry", function(accounts) { }); }); }); + describe("using composed signature", () => { + describe("as current owner", () => { + let tx; + const delegateType = "attestor"; + before(async () => { + previousChange = await didReg.changed(signerAddress); + const sig = await signData( + signerAddress, + signerAddress2, + privateKey2, + Buffer.from("revokeDelegate").toString("hex") + + stringToBytes32(delegateType) + + stripHexPrefix(delegate) + ); + tx = await didReg.methods['revokeDelegateSigned(address,bytes,bytes32,address)']( + signerAddress, + sig.signature, + web3.utils.asciiToHex(delegateType), + delegate, + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("validDelegate should be false", async () => { + const valid = await didReg.validDelegate( + signerAddress, + web3.utils.asciiToHex(delegateType), + delegate + ); + assert.equal(valid, false, "revoked delegate correctly"); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(signerAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDDelegateChanged"); + assert.equal(event.args.identity, signerAddress); + assert.equal(bytes32ToString(event.args.delegateType), delegateType); + assert.equal(event.args.delegate, delegate); + assert.isBelow( + event.args.validTo.toNumber(), + Math.floor(Date.now() / 1000) + 1 + ); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); + describe("using smart contract signature", () => { + describe("as current owner", () => { + let tx; + const delegateType = "attestor"; + const identityAddress = ERC1271Sample.address; + before(async () => { + previousChange = await didReg.changed(identityAddress); + const sig = await addContractSignature( + identityAddress, + erc1271Sample2, + Buffer.from("revokeDelegate").toString("hex") + + stringToBytes32(delegateType) + + stripHexPrefix(delegate) + ); + tx = await didReg.methods['revokeDelegateSigned(address,bytes,bytes32,address)']( + identityAddress, + sig.signature, + web3.utils.asciiToHex(delegateType), + delegate, + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("validDelegate should be false", async () => { + const valid = await didReg.validDelegate( + identityAddress, + web3.utils.asciiToHex(delegateType), + delegate + ); + assert.equal(valid, false, "revoked delegate correctly"); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDDelegateChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(bytes32ToString(event.args.delegateType), delegateType); + assert.equal(event.args.delegate, delegate); + assert.isBelow( + event.args.validTo.toNumber(), + Math.floor(Date.now() / 1000) + 1 + ); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); }); describe("setAttribute()", () => { @@ -497,8 +826,8 @@ contract("EthereumDIDRegistry", function(accounts) { previousChange = await didReg.changed(identity); tx = await didReg.setAttribute( identity, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), 86400, { from: owner } ); @@ -527,14 +856,14 @@ contract("EthereumDIDRegistry", function(accounts) { try { const tx = await didReg.setAttribute( identity, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), 86400, { from: badboy } ); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -562,8 +891,8 @@ contract("EthereumDIDRegistry", function(accounts) { sig.v, sig.r, sig.s, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), 86400, { from: badboy } ); @@ -587,6 +916,92 @@ contract("EthereumDIDRegistry", function(accounts) { }); }); }); + describe("using composed signature", () => { + describe("as current owner", () => { + let tx; + const attributeName = "encryptionKey"; + before(async () => { + previousChange = await didReg.changed(signerAddress); + const sig = await signData( + signerAddress, + signerAddress2, + privateKey2, + Buffer.from("setAttribute").toString("hex") + + stringToBytes32(attributeName) + + Buffer.from("mykey").toString("hex") + + leftPad(new BN(86400).toString(16)) + ); + tx = await didReg.methods['setAttributeSigned(address,bytes,bytes32,bytes,uint256)']( + signerAddress, + sig.signature, + web3.utils.asciiToHex(attributeName), + web3.utils.asciiToHex("mykey"), + 86400, + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(signerAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDAttributeChanged"); + assert.equal(event.args.identity, signerAddress); + assert.equal(bytes32ToString(event.args.name), attributeName); + assert.equal(event.args.value, "0x6d796b6579"); + assert.equal(event.args.validTo.toNumber(), block.timestamp + 86400); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); + describe("using smart contract signature", () => { + describe("as current owner", () => { + let tx; + const attributeName = "encryptionKey"; + const identityAddress = ERC1271Sample.address; + before(async () => { + previousChange = await didReg.changed(identityAddress); + const sig = await addContractSignature( + identityAddress, + erc1271Sample2, + Buffer.from("setAttribute").toString("hex") + + stringToBytes32(attributeName) + + Buffer.from("mykey").toString("hex") + + leftPad(new BN(86400).toString(16)) + ); + tx = await didReg.methods['setAttributeSigned(address,bytes,bytes32,bytes,uint256)']( + identityAddress, + sig.signature, + web3.utils.asciiToHex(attributeName), + web3.utils.asciiToHex("mykey"), + 86400, + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDAttributeChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(bytes32ToString(event.args.name), attributeName); + assert.equal(event.args.value, "0x6d796b6579"); + assert.equal(event.args.validTo.toNumber(), block.timestamp + 86400); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); }); describe("revokeAttribute()", () => { @@ -598,8 +1013,8 @@ contract("EthereumDIDRegistry", function(accounts) { previousChange = await didReg.changed(identity); tx = await didReg.revokeAttribute( identity, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), { from: owner } ); block = await getBlock(tx.receipt.blockNumber); @@ -627,13 +1042,13 @@ contract("EthereumDIDRegistry", function(accounts) { try { const tx = await didReg.revokeAttribute( identity, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), { from: badboy } ); assert.equal(tx, undefined, "this should not happen"); } catch (error) { - assert.equal( + assert.include( error.message, "VM Exception while processing transaction: revert" ); @@ -655,13 +1070,13 @@ contract("EthereumDIDRegistry", function(accounts) { stringToBytes32("encryptionKey") + Buffer.from("mykey").toString("hex") ); - tx = await didReg.revokeAttributeSigned( + tx = await didReg.methods['revokeAttributeSigned(address,uint8,bytes32,bytes32,bytes32,bytes)']( signerAddress, sig.v, sig.r, sig.s, - "encryptionKey", - "mykey", + web3.utils.asciiToHex("encryptionKey"), + web3.utils.asciiToHex("mykey"), { from: badboy } ); block = await getBlock(tx.receipt.blockNumber); @@ -684,6 +1099,88 @@ contract("EthereumDIDRegistry", function(accounts) { }); }); }); + describe("using composed signature", () => { + describe("as current owner", () => { + let tx; + const attributeName = "encryptionKey"; + before(async () => { + previousChange = await didReg.changed(signerAddress); + const sig = await signData( + signerAddress, + signerAddress2, + privateKey2, + Buffer.from("revokeAttribute").toString("hex") + + stringToBytes32(attributeName) + + Buffer.from("mykey").toString("hex") + ); + tx = await didReg.methods['revokeAttributeSigned(address,bytes,bytes32,bytes)']( + signerAddress, + sig.signature, + web3.utils.asciiToHex(attributeName), + web3.utils.asciiToHex("mykey"), + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(signerAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDAttributeChanged"); + assert.equal(event.args.identity, signerAddress); + assert.equal(bytes32ToString(event.args.name), attributeName); + assert.equal(event.args.value, "0x6d796b6579"); + assert.equal(event.args.validTo.toNumber(), 0); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); + describe("using smart contract signature", () => { + describe("as current owner", () => { + let tx; + const attributeName = "encryptionKey"; + const identityAddress = ERC1271Sample.address; + before(async () => { + previousChange = await didReg.changed(identityAddress); + const sig = await addContractSignature( + identityAddress, + erc1271Sample2, + Buffer.from("revokeAttribute").toString("hex") + + stringToBytes32(attributeName) + + Buffer.from("mykey").toString("hex") + ); + tx = await didReg.methods['revokeAttributeSigned(address,bytes,bytes32,bytes)']( + identityAddress, + sig.signature, + web3.utils.asciiToHex(attributeName), + web3.utils.asciiToHex("mykey"), + { from: badboy } + ); + block = await getBlock(tx.receipt.blockNumber); + }); + it("should sets changed to transaction block", async () => { + const latest = await didReg.changed(identityAddress); + assert.equal(latest, tx.receipt.blockNumber); + }); + it("should create DIDDelegateChanged event", () => { + const event = tx.logs[0]; + assert.equal(event.event, "DIDAttributeChanged"); + assert.equal(event.args.identity, identityAddress); + assert.equal(bytes32ToString(event.args.name), attributeName); + assert.equal(event.args.value, "0x6d796b6579"); + assert.equal(event.args.validTo.toNumber(), 0); + assert.equal( + event.args.previousChange.toNumber(), + previousChange.toNumber() + ); + }); + }); + }); }); describe("Events", () => { @@ -691,12 +1188,11 @@ contract("EthereumDIDRegistry", function(accounts) { const history = []; previousChange = await didReg.changed(identity); while (previousChange) { - const filter = await didReg.allEvents({ - topics: [identity], + const events = await didReg.getPastEvents('allEvents', { + identity: identity, fromBlock: previousChange, toBlock: previousChange }); - const events = await getLogs(filter); previousChange = undefined; for (let event of events) { history.unshift(event.event);